Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: getOrThrow / deleteOrThrowを追加 #2055

Merged
merged 9 commits into from
May 13, 2024
6 changes: 2 additions & 4 deletions src/components/Sing/SequencerPhraseIndicator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ const classNames: Record<PhraseState, string> = {
PLAYABLE: "playable",
};
const className = computed(() => {
const phrase = store.state.phrases.get(props.phraseKey);
if (phrase == undefined) {
throw new Error("phrase is undefined.");
}
const phrase = store.state.phrases.getOrThrow(props.phraseKey);

return classNames[phrase.state];
});
</script>
Expand Down
39 changes: 39 additions & 0 deletions src/helpers/strictMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Mapの拡張。
//
// - Mapを継承したStrictMapはimmerにより通常のMapになってしまう。
// - implements Map<K, V>のカスタムクラスはstructuredCloneにより{ map: Map<K, V> }になってしまう。
// そのため、Mapを直接拡張する。

const addProperty = (key: string, value: (...args: never[]) => unknown) => {
// @ts-expect-error 意図的にPrototype汚染をしている。
Map.prototype[key] = value;
};

addProperty(
"getOrThrow",
function (this: Map<unknown, unknown>, key: unknown): unknown {
if (!this.has(key)) {
throw new Error(`Key not found: ${key}`);
}
return this.get(key);
},
);

addProperty(
"deleteOrThrow",
function (this: Map<unknown, unknown>, key: unknown): void {
if (!this.has(key)) {
throw new Error(`Key not found: ${key}`);
}
this.delete(key);
},
);

declare global {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ちょっと詳しくないのですが、このファイルをimportしたら見えるようにする事って可能だったりしますか・・・?
というのも現状でelectronのメインプロセスから使えないのに見えるようになってて問題だな~~と感じたためです。

(その場合はaddPropertyが何度も実行されることも考えないといけないかも?)

interface Map<K, V> {
getOrThrow(key: K): V;
deleteOrThrow(key: K): void;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これが独自のものだと気づきやすいように、/** */でコメントを書いておくと良いかも


export {};
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "@/helpers/strictMap";
import { createApp } from "vue";
import { createGtm } from "@gtm-support/vue-gtm";
import { Quasar, Dialog, Loading, Notify } from "quasar";
Expand Down
44 changes: 16 additions & 28 deletions src/store/singing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,10 +607,8 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
phraseState,
}: { phraseKey: string; phraseState: PhraseState },
) {
const phrase = state.phrases.get(phraseKey);
if (phrase == undefined) {
throw new Error("phrase is undefined.");
}
const phrase = state.phrases.getOrThrow(phraseKey);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

念のために将来revertするかもと考えて、このコミットでの変更は最小限にしておくのはどうでしょう・・・?
src/components/Sing/SequencerPhraseIndicator.vueの1つだけにしておくとか。。

phrase.state = phraseState;
},
},
Expand All @@ -626,10 +624,8 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
singingGuideKey: SingingGuideSourceHash | undefined;
},
) {
const phrase = state.phrases.get(phraseKey);
if (phrase == undefined) {
throw new Error("phrase is undefined.");
}
const phrase = state.phrases.getOrThrow(phraseKey);

phrase.singingGuideKey = singingGuideKey;
},
},
Expand All @@ -645,10 +641,8 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
singingVoiceKey: SingingVoiceSourceHash | undefined;
},
) {
const phrase = state.phrases.get(phraseKey);
if (phrase == undefined) {
throw new Error("phrase is undefined.");
}
const phrase = state.phrases.getOrThrow(phraseKey);

phrase.singingVoiceKey = singingVoiceKey;
},
},
Expand Down Expand Up @@ -1200,12 +1194,10 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
phrase.singingGuideKey != undefined &&
phrase.singingVoiceKey != undefined
) {
let singingGuide = state.singingGuides.get(
let singingGuide = state.singingGuides.getOrThrow(
phrase.singingGuideKey,
);
if (singingGuide == undefined) {
throw new Error("singingGuide is undefined.");
}

// 歌い方をコピーして、ピッチ編集を適用する
singingGuide = structuredClone(toRaw(singingGuide));
applyPitchEdit(singingGuide, pitchEditData, editFrameRate);
Expand Down Expand Up @@ -1299,10 +1291,9 @@ export const singingStore = createPartialStore<SingingStoreTypes>({

let singingGuide: SingingGuide | undefined;
if (phrase.singingGuideKey != undefined) {
singingGuide = state.singingGuides.get(phrase.singingGuideKey);
if (!singingGuide) {
throw new Error("singingGuide is undefined.");
}
singingGuide = state.singingGuides.getOrThrow(
phrase.singingGuideKey,
);
} else {
const singingGuideSourceHash =
await calculateSingingGuideSourceHash({
Expand Down Expand Up @@ -2353,16 +2344,13 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
) {
continue;
}
const singingGuide = state.singingGuides.get(
const singingGuide = state.singingGuides.getOrThrow(
phrase.singingGuideKey,
);
const singingVoice = singingVoices.get(phrase.singingVoiceKey);
if (!singingGuide) {
throw new Error("singingGuide is undefined");
}
if (!singingVoice) {
throw new Error("singingVoice is undefined");
}
const singingVoice = singingVoices.getOrThrow(
phrase.singingVoiceKey,
);

// TODO: この辺りの処理を共通化する
const audioEvents = await generateAudioEvents(
offlineAudioContext,
Expand Down
Loading