Skip to content

Commit a7994be

Browse files
committed
decorator util
1 parent a8bc6f9 commit a7994be

File tree

3 files changed

+56
-44
lines changed

3 files changed

+56
-44
lines changed

src/component.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { defineComponent, type ComponentCustomOptions, type MethodOptions } from 'vue';
2-
import { obtainSlot, getSuperSlot, getProviderFunction } from './utils'
2+
import { obtainSlot, getSuperSlot, getProviderFunction, optionNullableClassDecorator } from './utils'
33
import { build as optionSetup } from './option/setup'
44
import { build as optionComputed } from './option/computed'
55
import { build as optionData } from './option/data'
@@ -15,7 +15,6 @@ import { build as optionAccessor } from './option/accessor'
1515
import type { SetupContext } from 'vue';
1616
import type { OptionBuilder } from './optionBuilder'
1717
import type { VueCons } from './class'
18-
import * as DecoratorCompatible from './deco3/utils'
1918
type SetupFunction<T> = (this: void, props: Readonly<any>, ctx: SetupContext<any>) => T | Promise<T>
2019
export type OptionSetupFunction = SetupFunction<any>
2120
export type ComponentSetupFunction = SetupFunction<Record<string, any>>
@@ -71,8 +70,6 @@ type ComponentOption = {
7170
methods?: MethodOptions
7271
}
7372

74-
type ComponentConsOption = VueCons | ComponentOption
75-
7673
function buildComponent(cons: VueCons, arg: ComponentOption, extend?: any): any {
7774
const option = ComponentOption(cons, extend)
7875
const slot = obtainSlot(cons.prototype)
@@ -164,22 +161,9 @@ function build(cons: VueCons, option: ComponentOption) {
164161
(cons as any).__vccOpts = component
165162
}
166163

167-
export function ComponentBase(arg: ComponentConsOption, ctx?: ClassDecoratorContext): any {
168-
function process(cons: VueCons, option: ComponentOption) {
169-
build(cons, option)
170-
return cons
171-
}
172-
if (typeof arg === 'function') {
173-
return DecoratorCompatible.compatibleClassDecorator(function (cons: VueCons) {
174-
return process(cons, {})
175-
})(arg, ctx)
176-
}
177-
return DecoratorCompatible.compatibleClassDecorator(function (cons: VueCons) {
178-
return process(cons, arg)
179-
})
180-
}
181-
182-
164+
export const ComponentBase = optionNullableClassDecorator((cons: VueCons, option?: ComponentOption) => {
165+
build(cons, option ?? {})
166+
})
183167

184168
export function toNative<T extends VueCons>(cons: T): T {
185169
const slot = obtainSlot(cons.prototype)

src/deco3/utils.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { VueCons } from '../class'
12
import { obtainSlot } from '../utils'
23
export const Compatible: {
34
fakePrototype?: any,
@@ -6,37 +7,38 @@ export const Compatible: {
67

78
}
89
export function compatibleClassDecorator(deco: Function) {
9-
return function (arg: any, ctx?: DecoratorContext) {
10-
11-
if (ctx) {//stage 3
12-
10+
return function (cons: VueCons, ctx?: ClassDecoratorContext) {
11+
if (ctx) {//stage 3 arg is constructor, ctx is ClassDecoratorContext
1312
if (ctx.kind !== 'class') {
1413
throw 'deco stage 3 class'
1514
}
1615
const proto = Compatible.fakePrototype ??= {}
1716
const slot = obtainSlot(proto)
1817
delete Compatible.fakePrototype
1918

20-
obtainSlot(arg.prototype, slot)
21-
const ret = deco(arg)
19+
obtainSlot(cons.prototype, slot)
20+
const ret = deco(cons)
2221

2322
return ret
2423
}
25-
else {
26-
27-
return deco(arg)
24+
else {//stage 2 arg is constructor
25+
return deco(cons)
2826
}
2927
}
3028
}
3129

3230
export function compatibleMemberDecorator(deco: Function) {
33-
return function (arg: any, ctx: DecoratorContext | string) {
34-
if (typeof ctx === 'object') {//stage 3
31+
return function (protoOrValue: any, nameOrCtx: ClassMemberDecoratorContext | string) {
32+
if (typeof nameOrCtx === 'object') {//stage 3 arg is value, ctx is ClassMemberDecoratorContext
33+
const ctx = nameOrCtx
34+
const value = protoOrValue
3535
const proto = Compatible.fakePrototype ??= {};
36-
proto[ctx.name!] = arg
36+
proto[ctx.name!] = value
3737
return deco(proto, ctx.name)
38-
} else {
39-
return deco(arg, ctx)
38+
} else { //stage 2 arg is prototype, ctx is name stirng
39+
const name = nameOrCtx
40+
const proto = protoOrValue
41+
return deco(proto, name)
4042
}
4143
}
4244
}

src/utils.ts

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Metadata } from 'facing-metadata'
2-
import { Base } from './index'
32
import type { Identity } from './identity'
43
import type { InjectConfig } from "./option/inject";
54
import type { EmitConfig } from "./option/emit";
@@ -11,7 +10,9 @@ import type { SetupConfig } from './option/setup'
1110
import type { Record as CustomDecoratorRecord } from './custom/custom'
1211
import type { RefConfig } from './option/ref';
1312
import type { ProvideConfig } from './option/provide';
14-
import { compatibleMemberDecorator } from './deco3/utils';
13+
import { compatibleMemberDecorator, compatibleClassDecorator } from './deco3/utils';
14+
import { type VueCons, Base } from './class';
15+
1516

1617
const SlotSymbol = Symbol('vue-facing-decorator-slot')
1718

@@ -62,7 +63,7 @@ export function makeSlot(obj: any, defaultSlot?: Slot): Slot {
6263
defaultSlot.master = obj
6364
}
6465
const slot = defaultSlot ?? new Slot(obj)
65-
metadata.create(obj,slot)
66+
metadata.create(obj, slot)
6667
return slot
6768
}
6869

@@ -152,25 +153,50 @@ export function getValidNames(obj: any, filter: (des: PropertyDescriptor, name:
152153
}
153154

154155
export function optionNullableMemberDecorator<T>(handler: { (proto: any, name: string, option?: T): any }) {
155-
function decorator(option?: T): any
156-
function decorator(proto: Identity, name: any): any
156+
function decorator(): any
157+
function decorator(option: T): any//option
158+
function decorator(proto: Identity, name: any): any//deco stage 2
157159
function decorator(value: any, ctx: ClassMemberDecoratorContext): any //deco stage 3
158-
function decorator(optionOrProto?: T | Identity | any, name?: string | ClassMemberDecoratorContext): any {
159-
if (name) {
160+
function decorator(optionOrProtoOrValue?: T | Identity | any, nameOrCtx?: string | ClassMemberDecoratorContext): any {
161+
if (nameOrCtx) {//no option
162+
const protoOrValue = optionOrProtoOrValue as Identity | any
160163
compatibleMemberDecorator(function (proto: any, name: any) {
161164
handler(proto, name)
162-
})(optionOrProto, name)
165+
})(protoOrValue, nameOrCtx)
163166
}
164-
else {
167+
else {//with option
168+
const option = optionOrProtoOrValue as T
165169
return compatibleMemberDecorator(function (proto: any, name: any) {
166-
handler(proto, name, optionOrProto as T | undefined)
170+
handler(proto, name, option as T | undefined)
167171
})
168172
}
169173
}
170174

171175
return decorator
172176
}
173177

178+
export function optionNullableClassDecorator<T>(handler: { (cons: VueCons, option?: T): any }) {
179+
function decorator(): any
180+
function decorator(option: T): any//option
181+
function decorator(cons: VueCons): any//deco stage 2
182+
function decorator(cons: VueCons, ctx: ClassDecoratorContext): any//deco stage 3
183+
function decorator(optionOrCons?: T | VueCons, ctx?: ClassDecoratorContext) {
184+
if (typeof optionOrCons === 'function') {
185+
const cons = optionOrCons as VueCons
186+
compatibleClassDecorator(function (cons: VueCons) {
187+
handler(cons)
188+
})(cons, ctx)
189+
190+
} else {
191+
const option = optionOrCons as T
192+
return compatibleClassDecorator(function (cons: VueCons) {
193+
handler(cons, option)
194+
})
195+
}
196+
}
197+
return decorator
198+
}
199+
174200
export function getProviderFunction(provide: any): () => {} {
175201
if (typeof provide === 'function') return provide
176202
return function () { return provide || {} }

0 commit comments

Comments
 (0)