diff --git a/lambda/mod.ts b/lambda/mod.ts index b4bc85d6..4e16f968 100644 --- a/lambda/mod.ts +++ b/lambda/mod.ts @@ -143,7 +143,7 @@ export function unregister( denops: Denops, id: Identifier, ): boolean { - if (id in denops.dispatcher) { + if (isRegisteredFnId(id) && id in denops.dispatcher) { delete denops.dispatcher[id]; return true; } @@ -293,3 +293,7 @@ const isFnWrapperArgs = isTupleOf([ isLiteralOneOf(["notify", "request"] as const), isArray, ]) satisfies Predicate; + +function isRegisteredFnId(id: unknown): id is Identifier { + return typeof id === "string" && id.startsWith("lambda:"); +} diff --git a/lambda/mod_test.ts b/lambda/mod_test.ts index acdf33a5..7fd28386 100644 --- a/lambda/mod_test.ts +++ b/lambda/mod_test.ts @@ -150,7 +150,7 @@ test({ await t.step("does not unregister lambda functions", async () => { const fn = spy(returnsNext(["foo"])); const id = lambda.register(denops, fn); - lambda.unregister(denops, "not-registered-id"); + lambda.unregister(denops, "lambda:not-registered-id"); assertSpyCalls(fn, 0); assertEquals( @@ -161,7 +161,35 @@ test({ assertSpyCalls(fn, 1); }); await t.step("returns `false`", () => { - assertEquals(lambda.unregister(denops, "not-registered-id"), false); + assertEquals( + lambda.unregister(denops, "lambda:not-registered-id"), + false, + ); + }); + }); + await t.step("if 'id' is not a lambda identifier", async (t) => { + await t.step("does not unregister method", async () => { + const fn = spy(returnsNext(["foo"])); + const notLambdaId = "not-lambda-id"; + denops.dispatcher = { + [notLambdaId]: fn, + }; + lambda.unregister(denops, notLambdaId); + + assertSpyCalls(fn, 0); + assertEquals( + await denops.dispatch(denops.name, notLambdaId), + "foo", + "The method is available", + ); + assertSpyCalls(fn, 1); + }); + await t.step("returns `false`", () => { + const notLambdaId = "not-lambda-id"; + denops.dispatcher = { + [notLambdaId]: () => "foo", + }; + assertEquals(lambda.unregister(denops, notLambdaId), false); }); }); });