Skip to content

Commit a40e1bf

Browse files
committed
a
1 parent 506739a commit a40e1bf

32 files changed

+254
-167
lines changed

src/component.ts

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import { build as optionAccessor } from './option/accessor'
1414
import type { SetupContext } from 'vue';
1515
import type { OptionBuilder } from './optionBuilder'
1616
import type { VueCons } from './index'
17+
import * as DecoratorCompatible from './deco3/utils'
1718
export type Cons = VueCons
1819

1920
type SetupFunction<T> = (this: void, props: Readonly<any>, ctx: SetupContext<any>) => T | Promise<T>
2021
export type OptionSetupFunction = SetupFunction<any>
2122
export type ComponentSetupFunction = SetupFunction<Record<string, any>>
2223
function ComponentOption(cons: Cons, extend?: any) {
23-
2424
const optionBuilder: OptionBuilder = {}
2525
optionSetup(cons, optionBuilder)
2626
optionVModel(cons, optionBuilder)
@@ -36,6 +36,7 @@ function ComponentOption(cons: Cons, extend?: any) {
3636
const setupFunction: OptionSetupFunction | undefined = optionBuilder.setup ? function (props, ctx) {
3737
return optionBuilder.setup!(props, ctx)
3838
} : undefined
39+
3940
const raw = {
4041
setup: setupFunction,
4142
data() {
@@ -85,29 +86,34 @@ function buildComponent(cons: Cons, arg: ComponentOption, extend?: any): any {
8586
emits = Array.from(new Set([...emits, ...arg.emits]))
8687
}
8788
option.emits = emits
88-
if (arg.setup) {
89-
if (!option.setup) {
90-
option.setup = arg.setup
91-
} else {
92-
const oldSetup: OptionSetupFunction = option.setup
93-
const newSetup: ComponentSetupFunction = arg.setup
89+
arg.setup ??= function () { return {} }
9490

95-
const setup: ComponentSetupFunction = function (props, ctx) {
96-
const newRet = newSetup(props, ctx)
97-
const oldRet = oldSetup(props, ctx)
98-
if (oldRet instanceof Promise || newRet instanceof Promise) {
99-
return Promise.all([newRet, oldRet]).then((arr) => {
100-
return Object.assign({}, arr[0], arr[1])
101-
})
102-
} else {
91+
if (!option.setup) {
10392

104-
return Object.assign({}, newRet, oldRet)
105-
}
93+
option.setup = arg.setup
94+
} else {
95+
96+
const oldSetup: OptionSetupFunction = option.setup
97+
const newSetup: ComponentSetupFunction = arg.setup
10698

99+
const setup: ComponentSetupFunction = function (props, ctx) {
100+
const newRet = newSetup(props, ctx)
101+
const oldRet = oldSetup(props, ctx)
102+
if (oldRet instanceof Promise || newRet instanceof Promise) {
103+
return Promise.all([newRet, oldRet]).then((arr) => {
104+
const ret = Object.assign({}, arr[0], arr[1])
105+
return ret
106+
})
107+
} else {
108+
109+
const ret = Object.assign({}, newRet, oldRet)
110+
return ret
107111
}
108-
option.setup = setup
112+
109113
}
114+
option.setup = setup
110115
}
116+
111117
if (arg.options) {
112118
Object.assign(option, arg.options)
113119
}
@@ -133,24 +139,33 @@ function build(cons: Cons, option: ComponentOption) {
133139
slot.cachedVueComponent = component
134140

135141
}
136-
function _Component(arg: ComponentConsOption, cb: (cons: Cons, option: ComponentOption) => any) {
142+
function _Component(cb: (cons: Cons, option: ComponentOption) => any, arg: ComponentConsOption, ctx?: ClassDecoratorContext) {
137143
if (typeof arg === 'function') {
138-
return cb(arg, {})
144+
return DecoratorCompatible.compatibleClassDecorator(function (cons: Cons) {
145+
return cb(cons, {})
146+
})(arg, ctx)
139147
}
140-
return function (cons: Cons) {
148+
return DecoratorCompatible.compatibleClassDecorator(function (cons: Cons) {
141149
return cb(cons, arg)
142-
}
150+
})
143151
}
144-
export function ComponentBase(arg: ComponentConsOption): any {
145-
return _Component(arg, function (cons: Cons, option: ComponentOption) {
152+
export function ComponentBase(arg: ComponentConsOption, ctx?: ClassDecoratorContext): any {
153+
return _Component(function (cons: Cons, option: ComponentOption) {
146154
build(cons, option)
147155
return cons
148-
})
156+
}, arg, ctx)
149157
}
150158

151-
export function Component(arg: ComponentConsOption): any {
152-
return _Component(arg, function (cons: Cons, option: ComponentOption) {
153-
build(cons, option)
154-
return obtainSlot(cons.prototype).cachedVueComponent
155-
})
159+
export const Component = ComponentBase
160+
161+
export function toNative<T extends Cons>(cons: T): T {
162+
const slot = obtainSlot(cons.prototype)
163+
if (!slot.inComponent) {
164+
throw 'to native 1'
165+
}
166+
const cached = slot.cachedVueComponent
167+
if (!cached) {
168+
throw 'to native 2'
169+
}
170+
return cached
156171
}

src/deco3/utils.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { obtainSlot } from '../utils'
2+
export const Compatible: {
3+
fakePrototype?: any,
4+
5+
} = {
6+
7+
}
8+
export function compatibleClassDecorator(deco: Function) {
9+
return function (arg: any, ctx?: DecoratorContext) {
10+
11+
if (ctx) {//stage 3
12+
13+
if (ctx.kind !== 'class') {
14+
throw 'deco stage 3 class'
15+
}
16+
const proto = Compatible.fakePrototype ??= {}
17+
const slot = obtainSlot(proto)
18+
delete Compatible.fakePrototype
19+
20+
obtainSlot(arg.prototype, slot)
21+
const ret = deco(arg)
22+
23+
return ret
24+
}
25+
else {
26+
27+
return deco(arg)
28+
}
29+
}
30+
}
31+
32+
export function compatibleMemberDecorator(deco: Function) {
33+
return function (arg: any, ctx: DecoratorContext | string) {
34+
if (typeof ctx === 'object') {//stage 3
35+
const proto = Compatible.fakePrototype ??= {}
36+
return deco(proto, ctx.name)
37+
} else {
38+
return deco(arg, ctx)
39+
}
40+
}
41+
}

src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,23 @@ export type VueCons<T = {}> = {
3131

3232
export const Base = class {
3333
constructor(optionBuilder: OptionBuilder, vueInstance: any) {
34+
3435
const props = optionBuilder.props
36+
3537
if (props) {
3638
Object.keys(props).forEach(key => {
37-
(this as any)[key] = vueInstance[key]
39+
(this as any)[key] = vueInstance[key];
3840
})
3941
}
42+
(global as any).kkk = this
43+
console.log('base', (this as any).prop)
44+
console.log('base', (global as any).kkk.prop)
45+
setTimeout(() => {
46+
console.log('base', (global as any).kkk.prop)
47+
}, 0);
4048
}
4149
} as VueCons
4250

4351
export const Vue = Base
52+
53+
export { toNative } from './component'

src/option/data.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ import { makeObject, obtainSlot, excludeNames, getValidNames } from '../utils'
44

55
export function build(cons: Cons, optionBuilder: OptionBuilder, vueInstance: any, _propNames?: string[]) {
66
optionBuilder.data ??= {}
7+
console.log('build1')
78
const sample = new cons(optionBuilder, vueInstance)
8-
let names = getValidNames(sample, (des) => {
9-
return !!des.enumerable
10-
})
11-
const slot = obtainSlot(cons.prototype)
12-
names = excludeNames(names, slot)
13-
Object.assign(optionBuilder.data, makeObject(names, sample))
9+
// console.log('in build',sample)
10+
// let names = getValidNames(sample, (des) => {
11+
// return !!des.enumerable
12+
// })
13+
14+
// const slot = obtainSlot(cons.prototype)
15+
// names = excludeNames(names, slot)
16+
17+
// Object.assign(optionBuilder.data, makeObject(names, sample))
1418
}

src/option/emit.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Cons } from '../component'
22
import type { OptionBuilder } from '../optionBuilder'
33
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
4+
import { compatibleMemberDecorator } from '../deco3/utils'
45
export type EmitConfig = null | string
56

67
export const decorator = optoinNullableMemberDecorator(function (proto: any, name: string, key?: string) {

src/option/inject.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { InjectionKey } from 'vue'
22
import type { Cons } from '../component'
33
import type { OptionBuilder } from '../optionBuilder'
44
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
5-
5+
import { compatibleMemberDecorator } from '../deco3/utils'
66
export interface InjectConfig {
77
from?: string | symbol | Symbol | InjectionKey<any>
88
default?: any

src/option/props.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Cons } from '../component'
22
import type { OptionBuilder } from '../optionBuilder'
33
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
4-
4+
import { compatibleMemberDecorator } from '../deco3/utils'
55
export interface PropsConfig {
66
type?: any
77
required?: boolean

src/option/ref.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Cons } from '../component'
22
import { type OptionBuilder, applyAccessors } from '../optionBuilder'
33
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
4-
4+
import { compatibleMemberDecorator } from '../deco3/utils'
55
export const decorator = optoinNullableMemberDecorator(function (proto: any, name: string) {
66
const slot = obtainSlot(proto)
77
const map = slot.obtainMap('ref')

src/option/setup.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { compatibleMemberDecorator} from '../deco3/utils'
12
import type { OptionSetupFunction } from '../component'
23
import type { Cons } from '../component'
34
import type { OptionBuilder } from '../optionBuilder'
@@ -8,14 +9,13 @@ export type SetupConfig = {
89
}
910

1011
export function decorator(setupFunction: OptionSetupFunction) {
11-
return function (proto: any, name: string) {
12+
return compatibleMemberDecorator(function (proto: any, name: string) {
1213
const slot = obtainSlot(proto)
1314
const map = slot.obtainMap('setup')
1415
map.set(name, {
1516
setupFunction
1617
})
17-
}
18-
18+
})
1919
}
2020

2121
const isPromise = (v: any): v is Promise<any> => v instanceof Promise
@@ -28,10 +28,13 @@ export function build(cons: Cons, optionBuilder: OptionBuilder) {
2828
return
2929
}
3030
const setup: OptionSetupFunction = function (props, ctx) {
31+
3132
const setupData: Record<string, any> = {};
3233
let promises: Promise<any>[] | null = null;
3334
for (const name of map.keys()) {
35+
3436
const setupState = map.get(name)!.setupFunction(props, ctx)
37+
3538
if (isPromise(setupState)) {
3639
promises ??= []
3740
promises.push(setupState.then((v) => {
@@ -49,5 +52,6 @@ export function build(cons: Cons, optionBuilder: OptionBuilder) {
4952
return setupData
5053
}
5154
}
55+
5256
optionBuilder.setup = setup
5357
}

src/option/vanilla.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
2-
2+
import { compatibleMemberDecorator } from '../deco3/utils'
33
export const decorator = optoinNullableMemberDecorator(function (proto: any, name: string) {
44
const slot = obtainSlot(proto)
55
const map = slot.obtainMap('vanilla')

0 commit comments

Comments
 (0)