提交 e0296241 编写于 作者: fxy060608's avatar fxy060608

wip(mp): base64url

上级 7bc2b65f
......@@ -38,14 +38,11 @@ function assert(
describe('compiler', () => {
test('scope', () => {
assert(
`<template slot="left"/>`,
`<block slot="left"/>`,
`<unicloud-db v-slot:default="{data, loading, error, options}" collection=""><view v-if="error">{{error.message}}</view><view v-else></view></unicloud-db>`,
`<unicloud-db v-s="{{['default']}}" collection="" v-i="2a9ec0b0-0" slot="default"><block wx:for="{{a}}" wx:for-item="v0" wx:key="c"><view wx:if="{{v0.a}}">{{v0.b}}</view><view wx:else></view></block></unicloud-db>`,
`(_ctx, _cache) => {
return {}
}`,
{
renderDataSpread: false,
}
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: s0 }); }, { name: 'default', vueId: '2a9ec0b0-0' }) }
}`
)
})
})
......@@ -23,6 +23,13 @@ describe('compiler: transform v-slot', () => {
`<custom v-s="{{['header','default','footer']}}" v-i="2a9ec0b0-0"><view slot="header"/><view slot="default"/><view slot="footer"/></custom>`,
`(_ctx, _cache) => {
return {}
}`
)
assert(
`<unicloud-db v-slot:default="{data, loading, error, options}" collection=""><view v-if="error">{{error.message}}</view><view v-else></view></unicloud-db>`,
`<unicloud-db v-s="{{['default']}}" slot="default" collection="" v-i="2a9ec0b0-0"><block wx:for="{{a}}" wx:for-item="v0" wx:key="c"><view wx:if="{{v0.a}}">{{v0.b}}</view><view wx:else></view></block></unicloud-db>`,
`(_ctx, _cache) => {
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: s0 }); }, { name: 'default', vueId: '2a9ec0b0-0' }) }
}`
)
})
......
......@@ -6,6 +6,7 @@ import {
isArray,
capitalize,
camelize,
hasOwn,
} from '@vue/shared'
import {
......@@ -25,7 +26,7 @@ import {
isCallExpression,
isIdentifier,
isSpreadElement,
CallExpression,
Identifier,
} from '@babel/types'
import {
DirectiveNode,
......@@ -523,28 +524,36 @@ function hasSpreadElement(expr: ObjectExpression): boolean {
if (isSpreadElement(prop)) {
return true
} else {
const objExpr = parseReturnObjExpr(prop as ObjectProperty)
if (objExpr) {
return hasSpreadElement(objExpr)
const returnStatement = parseReturnStatement(prop as ObjectProperty)
if (returnStatement) {
return hasSpreadElement(returnStatement.argument as ObjectExpression)
}
}
})
}
function parseReturnObjExpr(prop: ObjectProperty) {
// 目前硬编码识别 _f,应该读取 context.helperString
const returnObjExprMap = {
_f: 1, // _f(_ctx.items,()=>{return {}})
_w: 0, // _w(()=>{return {}})
}
function parseReturnStatement(prop: ObjectProperty) {
if (
isObjectProperty(prop) &&
isCallExpression(prop.value) &&
isIdentifier(prop.value.callee) &&
// 目前硬编码识别 _f,应该读取 context.helperString
prop.value.callee.name === '_f'
isIdentifier(prop.value.callee)
) {
return (
(
(prop.value.arguments[1] as ArrowFunctionExpression)
.body as BlockStatement
const { name } = prop.value.callee as Identifier
if (hasOwn(returnObjExprMap, name)) {
return (
(
prop.value.arguments[
returnObjExprMap[name]
] as ArrowFunctionExpression
).body as BlockStatement
).body[0] as ReturnStatement
).argument as ObjectExpression
}
}
}
......@@ -552,18 +561,12 @@ function transformObjectPropertyExpr(
prop: ObjectProperty,
context: TransformContext
) {
// vFor
const objExpr = parseReturnObjExpr(prop)
if (objExpr) {
// vFor,withScopedSlot
const returnStatement = parseReturnStatement(prop)
if (returnStatement) {
const objExpr = returnStatement.argument as ObjectExpression
if (hasSpreadElement(objExpr)) {
;(
(
(
(prop.value as CallExpression)
.arguments[1] as ArrowFunctionExpression
).body as BlockStatement
).body[0] as ReturnStatement
).argument = transformObjectSpreadExpr(objExpr, context)
returnStatement.argument = transformObjectSpreadExpr(objExpr, context)
}
}
return prop
......
......@@ -71,35 +71,30 @@ export const transformSlot: NodeTransform = (node, context) => {
)
break
}
const slotName = findSlotName(slotDir)
if (!slotName) {
continue
}
slots.add(slotName)
const { exp } = slotDir
// non scoped slots
if (!exp) {
continue
}
// empty
if (exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {
continue
const slotName = transformTemplateSlotElement(
slotDir,
slotElement,
node,
context
)
if (slotName) {
slots.add(slotName)
}
slots.add(slotName)
// 使用vFor来简单处理scoped slot作用域问题
slotElement.children = [
createVForTemplate(
slotElement,
{ name: slotName, value: genExpr(exp), slotComponent: node },
context
),
]
// v-slot="slotProps" => v-slot 避免 transformIdentifier 生成 slotProps 的变量声明
slotDir.exp = undefined
}
if (implicitDefaultChildren.length) {
slots.add('default')
}
if (onComponentSlot) {
// <unicloud-db v-slot:default="{data, loading, error, options}"/>
// => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db>
slots.add('default')
const templateNode = createTemplateNode(
onComponentSlot,
implicitDefaultChildren
)
transformTemplateSlotElement(onComponentSlot, templateNode, node, context)
node.children = templateNode.children
}
if (slots.size) {
node.props.unshift(
createBindDirectiveNode(
......@@ -110,6 +105,56 @@ export const transformSlot: NodeTransform = (node, context) => {
}
}
function transformTemplateSlotElement(
slotDir: DirectiveNode,
slotTemplate: TemplateNode,
slotComponent: ComponentNode,
context: TransformContext
) {
const slotName = findSlotName(slotDir)
if (!slotName) {
return
}
const { exp } = slotDir
// non scoped slots
if (!exp) {
return slotName
}
// empty
if (exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {
return slotName
}
// 使用vFor来简单处理scoped slot作用域问题
slotTemplate.children = [
createVForTemplate(
slotTemplate,
{ name: slotName, value: genExpr(exp), slotComponent },
context
),
]
// v-slot="slotProps" => v-slot 避免 transformIdentifier 生成 slotProps 的变量声明
slotDir.exp = undefined
return slotName
}
function createTemplateNode(
slotDir: DirectiveNode,
children: TemplateChildNode[]
): TemplateNode {
return {
type: NodeTypes.ELEMENT,
tag: 'template',
tagType: ElementTypes.TEMPLATE,
loc: locStub,
isSelfClosing: false,
codegenNode: undefined,
ns: 0,
props: [slotDir],
children,
}
}
export function findSlotName(slotDir: DirectiveNode) {
if (!slotDir.arg) {
return 'default'
......
......@@ -18,6 +18,7 @@
},
"license": "Apache-2.0",
"dependencies": {
"base64url": "^3.0.1",
"magic-string": "^0.25.7"
},
"gitHead": "1efa8efd0a9eddeabdba75c020d015ebf31b8177"
......
......@@ -6,14 +6,15 @@ import {
removeExt,
} from '@dcloudio/uni-cli-shared'
import { Plugin } from 'vite'
import base64url from 'base64url'
import { UniMiniProgramPluginOptions } from '../plugin'
function encode(str: string) {
return Buffer.from(str).toString('base64url')
return base64url.encode(str)
}
function decode(str: string) {
return Buffer.from(str, 'base64url').toString()
return base64url.decode(str)
}
const uniPagePrefix = 'uniPage://'
......
......@@ -3413,6 +3413,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64url@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册