Potential memory leak or dead recursive during auto completion
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- typescript
- 领域
- compilers
调研方向
从链接的 TypeScript Playground 复现示例和提供的递归 PipelineBuilderState 类型开始,然后在监控内存和响应性的同时触发自动补全。比较移除重复的 post_delay 成员后的行为,并确定编译器是否会进入无界工作。完成标准是:复现示例在自动补全期间不再泄漏内存或变得无响应,并且相关行为已由回归测试覆盖。
由索引模型根据 Issue 内容生成。
描述
🔎 Search Terms
memory leak auto completion
🕗 Version & Regression Information
seems occur since first version that could compile those code.
Please forgive me for providing such a huge source code, as its complexity has to be kept to cause noticeable memory consumption rate (about 30MB/s, at least).
⏯ Playground Link
💻 Code
type RecoType =
| 'DirectHit'
| 'TemplateMatch'
| 'FeatureMatch'
| 'ColorMatch'
| 'OCR'
| 'NeuralNetworkClassify'
| 'NeuralNetworkDetect'
| 'Custom'
type ActType =
| 'DoNothing'
| 'Click'
| 'Swipe'
| 'Key'
| 'Text'
| 'StartApp'
| 'StopApp'
| 'StopTask'
| 'Custom'
type OrderByMap = {
TemplateMatch: 'Horizontal' | 'Vertical' | 'Score' | 'Random'
FeatureMatch: 'Horizontal' | 'Vertical' | 'Score' | 'Area' | 'Random'
ColorMatch: 'Horizontal' | 'Vertical' | 'Score' | 'Area' | 'Random'
OCR: 'Horizontal' | 'Vertical' | 'Area' | 'Length' | 'Random'
NeuralNetworkClassify: 'Horizontal' | 'Vertical' | 'Score' | 'Random'
NeuralNetworkDetect: 'Horizontal' | 'Vertical' | 'Score' | 'Area' | 'Random'
}
type PipelineBuilderState<Json = {}> = {
done: Json
} & ('recognition' extends keyof Json
? {}
: {
recognition<R extends RecoType>(
reco: R
): PipelineRecognitionBuilderState<
Json & {
recognition: R
},
R
>
}) &
('action' extends keyof Json
? {}
: {
action<A extends ActType>(
act: A
): PipelineActionBuilderState<
Json & {
action: A
},
A
>
}) &
('next' extends keyof Json
? {}
: {
next<N extends string[]>(...nxt: [...N]): PipelineBuilderState<Json & { next: N }>
}) &
('interrupt' extends keyof Json
? {}
: {
interrupt<I extends string[]>(
...int: [...I]
): PipelineBuilderState<Json & { interrupt: I }>
}) &
('rate_limit' extends keyof Json
? {}
: {
rate_limit<R extends number>(rate: R): PipelineBuilderState<Json & { rate_limit: R }>
}) &
('timeout' extends keyof Json
? {}
: {
timeout<R extends number>(time: R): PipelineBuilderState<Json & { timeout: R }>
}) &
('on_error' extends keyof Json
? {}
: {
on_error<O extends string[]>(
...err: [...O]
): PipelineBuilderState<Json & { on_error: O }>
}) &
('inverse' extends keyof Json
? {}
: {
inverse<I extends boolean>(inv: I): PipelineBuilderState<Json & { inverse: I }>
}) &
('enabled' extends keyof Json
? {}
: {
enabled<E extends boolean>(en: E): PipelineBuilderState<Json & { enabled: E }>
}) &
('pre_delay' extends keyof Json
? {}
: {
pre_delay<P extends number>(pre: P): PipelineBuilderState<Json & { pre_delay: P }>
}) &
('post_delay' extends keyof Json // <--- here two post_delay are provided, which is the root cause
? {}
: {
post_delay<P extends number>(post: P): PipelineBuilderState<Json & { post_delay: P }>
}) &
('post_delay' extends keyof Json // <---
? {}
: {
post_delay<P extends number>(post: P): PipelineBuilderState<Json & { post_delay: P }>
}) &
('pre_wait_freezes' extends keyof Json
? {}
: {
pre_wait_freezes: PipelineWaitFreezeBuilderState<Json, 'pre_wait_freezes'>
}) &
('focus' extends keyof Json
? {}
: {
focus<F extends boolean>(focus: F): PipelineBuilderState<Json & { focus: F }>
})
type PipelineRecognitionBuilderState<PBJson, Reco extends RecoType, Json = {}> = {
done: PipelineBuilderState<PBJson & Json>
} & (Reco extends 'DirectHit'
? {}
: ('roi' extends keyof Json
? {}
: {
roi<R extends [string] | [number, number, number, number]>(
...roi: R
): PipelineRecognitionBuilderState<
PBJson,
Reco,
Json & { roi: R extends [number, number, number, number] ? R : R[0] }
>
}) &
('roi_offset' extends keyof Json
? {}
: {
roi_offset<R extends [number, number, number, number]>(
...roi: R
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { roi_offset: R }>
})) &
(Reco extends 'TemplateMatch' | 'FeatureMatch'
? 'template' extends keyof Json
? {}
: {
template<T extends string[]>(
...templ: [...T]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { template: T }>
}
: {}) &
(Reco extends 'TemplateMatch' | 'NeuralNetworkDetect'
? 'threshold' extends keyof Json
? {}
: {
threshold<T extends number[]>(
...thres: [...T]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { threshold: T }>
threshold$<T extends number>(
thres: T
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { threshold: T }>
}
: {}) &
(Reco extends keyof OrderByMap
? 'order_by' extends keyof Json
? {}
: {
order_by<O extends OrderByMap[Reco]>(
order: O
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { order_by: O }>
}
: {}) &
(Reco extends keyof OrderByMap
? 'index' extends keyof Json
? {}
: {
index<T extends number>(
idx: T
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { index: T }>
}
: {}) &
(Reco extends 'TemplateMatch'
? 'method' extends keyof Json
? {}
: {
method<M extends 1 | 3 | 5>(
method: M
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { method: M }>
}
: {}) &
(Reco extends 'ColorMatch'
? 'method' extends keyof Json
? {}
: {
method<M extends 4 | 40 | 6>(
method: M
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { method: M }>
}
: {}) &
(Reco extends 'TemplateMatch' | 'FeatureMatch'
? 'green_mask' extends keyof Json
? {}
: {
green_mask<G extends boolean>(
mask: G
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { green_mask: G }>
}
: {}) &
(Reco extends 'FeatureMatch' | 'ColorMatch'
? 'count' extends keyof Json
? {}
: {
count<C extends number>(
count: C
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { count: C }>
}
: {}) &
(Reco extends 'FeatureMatch'
? 'detector' extends keyof Json
? {}
: {
detector<D extends 'SIFT' | 'KAZE' | 'AKAZE' | 'BRISK' | 'ORB'>(
det: D
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { detector: D }>
}
: {}) &
(Reco extends 'FeatureMatch'
? 'ratio' extends keyof Json
? {}
: {
ratio<R extends number>(
ratio: R
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { ratio: R }>
}
: {}) &
(Reco extends 'ColorMatch'
? 'method' extends keyof Json
? ('lower' extends keyof Json
? {}
: Json['method'] extends 4 | 40
? {
lower<L extends [number, number, number][]>(
...lower: [...L]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { lower: L }>
}
: {
lower<L extends [number][]>(
...lower: [...L]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { lower: L }>
}) &
('upper' extends keyof Json
? {}
: Json['method'] extends 4 | 40
? {
upper<L extends [number, number, number][]>(
...upper: [...L]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { upper: L }>
}
: {
upper<U extends [number][]>(
...upper: [...U]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { upper: U }>
})
: {}
: {}) &
(Reco extends 'ColorMatch'
? 'connected' extends keyof Json
? {}
: {
connected<C extends boolean>(
conn: C
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { connected: C }>
}
: {}) &
(Reco extends 'OCR'
? 'expected' extends keyof Json
? {}
: {
expected<E extends string[]>(
...exp: [...E]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { expected: E }>
}
: {}) &
(Reco extends 'NeuralNetworkClassify' | 'NeuralNetworkDetect'
? 'expected' extends keyof Json
? {}
: {
expected<E extends number[]>(
...exp: [...E]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { expected: E }>
}
: {}) &
(Reco extends 'OCR'
? 'replace' extends keyof Json
? {}
: {
replace<R extends [string, string][]>(
...exp: [...R]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { replace: R }>
}
: {}) &
(Reco extends 'OCR'
? 'only_rec' extends keyof Json
? {}
: {
only_rec<O extends boolean>(
rec: O
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { only_rec: O }>
}
: {}) &
(Reco extends 'OCR' | 'NeuralNetworkClassify' | 'NeuralNetworkDetect'
? 'model' extends keyof Json
? {}
: {
model<M extends string>(
model: M
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { model: M }>
}
: {}) &
(Reco extends 'NeuralNetworkClassify' | 'NeuralNetworkDetect'
? 'labels' extends keyof Json
? {}
: {
labels<L extends string[]>(
...label: [...L]
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { labels: L }>
}
: {}) &
(Reco extends 'Custom'
? 'custom_recognition' extends keyof Json
? {}
: {
custom_recognition<C extends string>(
reco: C
): PipelineRecognitionBuilderState<PBJson, Reco, Json & { custom_recognition: C }>
}
: {}) &
(Reco extends 'Custom'
? 'custom_recognition_param' extends keyof Json
? {}
: {
custom_recognition_param<C extends Record<string, unknown>>(
param: C
): PipelineRecognitionBuilderState<
PBJson,
Reco,
Json & { custom_recognition_param: C }
>
}
: {})
type PipelineActionBuilderState<PBJson, Act extends ActType, Json = {}> = {
done: PipelineBuilderState<PBJson & Json>
} & (Act extends 'Click' | 'Custom'
? 'target' extends keyof Json
? {}
: {
target<T extends [true] | [string] | [number, number, number, number]>(
...target: T
): PipelineActionBuilderState<
PBJson,
Act,
Json & { target: T extends [number, number, number, number] ? T : T[0] }
>
}
: {}) &
(Act extends 'Click' | 'Custom'
? 'target_offset' extends keyof Json
? {}
: {
target_offset<O extends [number, number, number, number]>(
...offset: O
): PipelineActionBuilderState<PBJson, Act, Json & { target_offset: O }>
}
: {}) &
(Act extends 'Swipe'
? 'begin' extends keyof Json
? {}
: {
begin<B extends [true] | [string] | [number, number, number, number]>(
...begin: B
): PipelineActionBuilderState<
PBJson,
Act,
Json & { begin: B extends [number, number, number, number] ? B : B[0] }
>
}
: {}) &
(Act extends 'Swipe'
? 'begin_offset' extends keyof Json
? {}
: {
begin_offset<B extends [number, number, number, number]>(
...offset: B
): PipelineActionBuilderState<PBJson, Act, Json & { begin_offset: B }>
}
: {}) &
(Act extends 'Swipe'
? 'end' extends keyof Json
? {}
: {
end<E extends [true] | [string] | [number, number, number, number]>(
...end: E
): PipelineActionBuilderState<
PBJson,
Act,
Json & { end: E extends [number, number, number, number] ? E : E[0] }
>
}
: {}) &
(Act extends 'Swipe'
? 'end_offset' extends keyof Json
? {}
: {
end_offset<E extends [number, number, number, number]>(
...offset: E
): PipelineActionBuilderState<PBJson, Act, Json & { end_offset: E }>
}
: {}) &
(Act extends 'Key'
? 'key' extends keyof Json
? {}
: {
key<K extends number[]>(
...key: [...K]
): PipelineActionBuilderState<PBJson, Act, Json & { key: K }>
}
: {}) &
(Act extends 'InputText'
? 'input_text' extends keyof Json
? {}
: {
input_text<T extends string>(
text: T
): PipelineActionBuilderState<PBJson, Act, Json & { input_text: T }>
}
: {}) &
(Act extends 'StartApp' | 'StopApp'
? 'package' extends keyof Json
? {}
: {
package<P extends string>(
pkg: P
): PipelineActionBuilderState<PBJson, Act, Json & { package: P }>
}
: {}) &
(Act extends 'Custom'
? 'custom_action' extends keyof Json
? {}
: {
custom_action<C extends string>(
act: C
): PipelineActionBuilderState<PBJson, Act, Json & { custom_action: C }>
}
: {}) &
(Act extends 'Custom'
? 'custom_action_param' extends keyof Json
? {}
: {
custom_action_param<C extends Record<string, unknown>>(
param: C
): PipelineActionBuilderState<PBJson, Act, Json & { custom_action_param: C }>
}
: {})
type PipelineWaitFreezeBuilderState<
PBJson,
Key extends 'pre_wait_freezes' | 'post_wait_freezes',
Json = {}
> = {
done: PipelineBuilderState<
PBJson & {
[key in Key]: Json
}
>
} & ('time' extends keyof Json
? {}
: {
time<T extends number>(
time: T
): PipelineWaitFreezeBuilderState<PBJson, Key, Json & { time: T }>
}) &
('target' extends keyof Json
? {}
: {
target<T extends [true] | [string] | [number, number, number, number]>(
...target: T
): PipelineWaitFreezeBuilderState<
PBJson,
Key,
Json & { target: T extends [number, number, number, number] ? T : T[0] }
>
}) &
('target_offset' extends keyof Json
? {}
: {
target_offset<O extends [number, number, number, number]>(
...offset: O
): PipelineWaitFreezeBuilderState<PBJson, Key, Json & { target_offset: O }>
}) &
('threshold' extends keyof Json
? {}
: {
threshold<T extends number>(
thres: T
): PipelineWaitFreezeBuilderState<PBJson, Key, Json & { threshold: T }>
}) &
('method' extends keyof Json
? {}
: {
method<M extends 1 | 3 | 5>(
met: M
): PipelineWaitFreezeBuilderState<PBJson, Key, Json & { method: M }>
}) &
('rate_limit' extends keyof Json
? {}
: {
rate_limit<R extends number>(
rate: R
): PipelineWaitFreezeBuilderState<PBJson, Key, Json & { rate_limit: R }>
})
const v = ({} as PipelineBuilderState).action('Click').done.
🙁 Actual behavior
When requesting auto completion in the last row (via dot), the heap raise quickly.
I've checked out that it is caused by the miss duplication of post_delay property state changing edge.
🙂 Expected behavior
The completion should either fail or succeed quickly. The duplicate edge shouldn't affect completing.
Additional information about the issue
No response
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.4k
- 平均合并
- 1 天 19 小时
- 30 天内合并 PR
- 117
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
microsoft/TypeScript 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 88/100
microsoft/TypeScript#64322 · 2 条评论 · 1 个 reaction · 已指派 2 人 ·
-
Possible Improvement
难度 2/5 1-3 小时 新手友好度 78/100
microsoft/TypeScript#64278 · 1 条评论 · 1 个 reaction ·
-
Docs
难度 2/5 1-3 小时 新手友好度 70/100
microsoft/TypeScript#64118 · 1 条评论 ·
-
难度 1/5 1 小时以内 新手友好度 88/100
microsoft/TypeScript#64094 ·
-
Docs
难度 2/5 1-3 小时 新手友好度 76/100
microsoft/TypeScript#63959 · 5 条评论 ·
查看 microsoft/TypeScript 的全部 Issue
相似的 Issue
-
kind/bug
难度 2/5 1-3 小时 新手友好度 88/100
kubernetes-sigs/prow#953 · 1 条评论 ·
-
难度 2/5 1-3 小时 新手友好度 88/100
caddyserver/caddy#8046 ·
-
难度 2/5 1-3 小时 新手友好度 86/100
-
L1 recommended for recruits
难度 2/5 1-3 小时 新手友好度 88/100
-
area/entangle bug
难度 1/5 1 小时以内 新手友好度 92/100