fix(ext): enable prefer-primordials for internal TypeScript (#21813)

Enabled prefer-primordials lint for ext/cron and ext/kv.
This commit is contained in:
Kenta Moriuchi 2024-01-08 07:20:02 +09:00 committed by GitHub
parent a731647a51
commit c2c115ebd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 62 deletions

View file

@ -1,7 +1,16 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { core, internals } from "ext:core/mod.js";
import { core, internals, primordials } from "ext:core/mod.js";
const {
ArrayPrototypeJoin,
NumberPrototypeToString,
TypeError,
} = primordials;
const {
isPromise,
} = core;
const {
op_cron_create,
op_cron_next,
} = core.ensureFastOps();
@ -15,7 +24,7 @@ export function formatToCronSchedule(
if (value === undefined) {
return "*";
} else if (typeof value === "number") {
return value.toString();
return NumberPrototypeToString(value);
} else {
const { exact } = value as { exact: number | number[] };
if (exact === undefined) {
@ -39,9 +48,9 @@ export function formatToCronSchedule(
}
} else {
if (typeof exact === "number") {
return exact.toString();
return NumberPrototypeToString(exact);
} else {
return exact.join(",");
return ArrayPrototypeJoin(exact, ",");
}
}
}
@ -104,7 +113,7 @@ function cron(
throw new TypeError("Deno.cron requires a handler");
}
const rid = core.ops.op_cron_create(
const rid = op_cron_create(
name,
schedule,
options?.backoffSchedule,
@ -130,7 +139,7 @@ function cron(
}
try {
const result = handler();
const _res = result instanceof Promise ? (await result) : result;
const _res = isPromise(result) ? (await result) : result;
success = true;
} catch (error) {
console.error(`Exception in cron handler ${name}`, error);

View file

@ -4,17 +4,35 @@ import { core, primordials } from "ext:core/mod.js";
import { SymbolDispose } from "ext:deno_web/00_infra.js";
import { ReadableStream } from "ext:deno_web/06_streams.js";
const {
ArrayFrom,
ArrayPrototypeMap,
ArrayPrototypePush,
ArrayPrototypeReverse,
ArrayPrototypeSlice,
AsyncGeneratorPrototype,
BigInt,
BigIntPrototypeToString,
Error,
NumberIsNaN,
Object,
ObjectFreeze,
ObjectGetPrototypeOf,
ObjectHasOwn,
ObjectPrototypeIsPrototypeOf,
RangeError,
SafeMap,
SafeMapIterator,
StringPrototypeReplace,
Symbol,
SymbolAsyncIterator,
SymbolFor,
SymbolToStringTag,
TypeError,
TypedArrayPrototypeGetSymbolToStringTag,
Error,
} = primordials;
const {
isPromise,
} = core;
const {
op_kv_atomic_write,
op_kv_database_open,
@ -46,7 +64,7 @@ function validateQueueDelay(delay: number) {
if (delay > maxQueueDelay) {
throw new TypeError("delay cannot be greater than 30 days");
}
if (isNaN(delay)) {
if (NumberIsNaN(delay)) {
throw new TypeError("delay cannot be NaN");
}
}
@ -58,8 +76,12 @@ function validateBackoffSchedule(backoffSchedule: number[]) {
if (backoffSchedule.length > maxQueueBackoffIntervals) {
throw new TypeError("invalid backoffSchedule");
}
for (const interval of backoffSchedule) {
if (interval < 0 || interval > maxQueueBackoffInterval || isNaN(interval)) {
for (let i = 0; i < backoffSchedule.length; ++i) {
const interval = backoffSchedule[i];
if (
interval < 0 || interval > maxQueueBackoffInterval ||
NumberIsNaN(interval)
) {
throw new TypeError("invalid backoffSchedule");
}
}
@ -108,7 +130,7 @@ class Kv {
}
async get(key: Deno.KvKey, opts?: { consistency?: Deno.KvConsistencyLevel }) {
const [entries]: [RawKvEntry[]] = await op_kv_snapshot_read(
const { 0: entries }: [RawKvEntry[]] = await op_kv_snapshot_read(
this.#rid,
[[
null,
@ -136,7 +158,7 @@ class Kv {
): Promise<Deno.KvEntry<unknown>[]> {
const ranges: RawKvEntry[][] = await op_kv_snapshot_read(
this.#rid,
keys.map((key) => [
ArrayPrototypeMap(keys, (key: Deno.KvKey) => [
null,
key,
null,
@ -146,7 +168,7 @@ class Kv {
]),
opts?.consistency ?? "strong",
);
return ranges.map((entries, i) => {
return ArrayPrototypeMap(ranges, (entries: RawKvEntry[], i: number) => {
if (!entries.length) {
return {
key: keys[i],
@ -215,12 +237,12 @@ class Kv {
consistency: Deno.KvConsistencyLevel,
) => Promise<Deno.KvEntry<unknown>[]> {
return async (selector, cursor, reverse, consistency) => {
const [entries]: [RawKvEntry[]] = await op_kv_snapshot_read(
const { 0: entries }: [RawKvEntry[]] = await op_kv_snapshot_read(
this.#rid,
[[
"prefix" in selector ? selector.prefix : null,
"start" in selector ? selector.start : null,
"end" in selector ? selector.end : null,
ObjectHasOwn(selector, "prefix") ? selector.prefix : null,
ObjectHasOwn(selector, "start") ? selector.start : null,
ObjectHasOwn(selector, "end") ? selector.end : null,
batchSize,
reverse,
cursor,
@ -228,7 +250,7 @@ class Kv {
consistency,
);
return entries.map(deserializeValue);
return ArrayPrototypeMap(entries, deserializeValue);
};
}
@ -270,7 +292,7 @@ class Kv {
if (this.#isClosed) {
throw new Error("already closed");
}
const finishMessageOps = new Map<number, Promise<void>>();
const finishMessageOps = new SafeMap<number, Promise<void>>();
while (true) {
// Wait for the next message.
const next: { 0: Uint8Array; 1: number } =
@ -292,7 +314,7 @@ class Kv {
let success = false;
try {
const result = handler(deserializedPayload);
const _res = result instanceof Promise ? (await result) : result;
const _res = isPromise(result) ? (await result) : result;
success = true;
} catch (error) {
console.error("Exception in queue handler", error);
@ -311,7 +333,7 @@ class Kv {
})();
}
for (const promise of finishMessageOps.values()) {
for (const { 1: promise } of new SafeMapIterator(finishMessageOps)) {
await promise;
}
finishMessageOps.clear();
@ -320,9 +342,8 @@ class Kv {
watch(keys: Deno.KvKey[], options = {}) {
const raw = options.raw ?? false;
const rid = op_kv_watch(this.#rid, keys);
const lastEntries: (Deno.KvEntryMaybe<unknown> | undefined)[] = Array.from(
const lastEntries: (Deno.KvEntryMaybe<unknown> | undefined)[] = ArrayFrom(
{ length: keys.length },
() => undefined,
);
return new ReadableStream({
async pull(controller) {
@ -360,7 +381,7 @@ class Kv {
changed = true;
if (updates[i] === null) {
lastEntries[i] = {
key: [...keys[i]],
key: ArrayPrototypeSlice(keys[i]),
value: null,
versionstamp: null,
};
@ -369,8 +390,12 @@ class Kv {
}
}
if (!changed && !raw) continue; // no change
const entries = lastEntries.map((entry) =>
entry.versionstamp === null ? { ...entry } : deserializeValue(entry)
const entries = ArrayPrototypeMap(
lastEntries,
(entry) =>
entry.versionstamp === null
? { ...entry }
: deserializeValue(entry),
);
controller.enqueue(entries);
return;
@ -404,14 +429,16 @@ class AtomicOperation {
}
check(...checks: Deno.AtomicCheck[]): this {
for (const check of checks) {
this.#checks.push([check.key, check.versionstamp]);
for (let i = 0; i < checks.length; ++i) {
const check = checks[i];
ArrayPrototypePush(this.#checks, [check.key, check.versionstamp]);
}
return this;
}
mutate(...mutations: Deno.KvMutation[]): this {
for (const mutation of mutations) {
for (let i = 0; i < mutations.length; ++i) {
const mutation = mutations[i];
const key = mutation.key;
let type: string;
let value: RawValue | null;
@ -432,7 +459,7 @@ class AtomicOperation {
case "min":
case "max":
type = mutation.type;
if (!("value" in mutation)) {
if (!ObjectHasOwn(mutation, "value")) {
throw new TypeError(`invalid mutation '${type}' without value`);
}
value = serializeValue(mutation.value);
@ -440,23 +467,38 @@ class AtomicOperation {
default:
throw new TypeError("Invalid mutation type");
}
this.#mutations.push([key, type, value, expireIn]);
ArrayPrototypePush(this.#mutations, [key, type, value, expireIn]);
}
return this;
}
sum(key: Deno.KvKey, n: bigint): this {
this.#mutations.push([key, "sum", serializeValue(new KvU64(n)), undefined]);
ArrayPrototypePush(this.#mutations, [
key,
"sum",
serializeValue(new KvU64(n)),
undefined,
]);
return this;
}
min(key: Deno.KvKey, n: bigint): this {
this.#mutations.push([key, "min", serializeValue(new KvU64(n)), undefined]);
ArrayPrototypePush(this.#mutations, [
key,
"min",
serializeValue(new KvU64(n)),
undefined,
]);
return this;
}
max(key: Deno.KvKey, n: bigint): this {
this.#mutations.push([key, "max", serializeValue(new KvU64(n)), undefined]);
ArrayPrototypePush(this.#mutations, [
key,
"max",
serializeValue(new KvU64(n)),
undefined,
]);
return this;
}
@ -465,7 +507,7 @@ class AtomicOperation {
value: unknown,
options?: { expireIn?: number },
): this {
this.#mutations.push([
ArrayPrototypePush(this.#mutations, [
key,
"set",
serializeValue(value),
@ -475,7 +517,7 @@ class AtomicOperation {
}
delete(key: Deno.KvKey): this {
this.#mutations.push([key, "delete", null, undefined]);
ArrayPrototypePush(this.#mutations, [key, "delete", null, undefined]);
return this;
}
@ -493,7 +535,7 @@ class AtomicOperation {
if (opts?.backoffSchedule !== undefined) {
validateBackoffSchedule(opts?.backoffSchedule);
}
this.#enqueues.push([
ArrayPrototypePush(this.#enqueues, [
core.serialize(message, { forStorage: true }),
opts?.delay ?? 0,
opts?.keysIfUndelivered ?? [],
@ -537,7 +579,7 @@ class KvU64 {
throw new RangeError("value must fit in a 64-bit unsigned integer");
}
this.value = value;
Object.freeze(this);
ObjectFreeze(this);
}
valueOf() {
@ -593,6 +635,7 @@ function serializeValue(value: unknown): RawValue {
} else if (ObjectPrototypeIsPrototypeOf(KvU64.prototype, value)) {
return {
kind: "u64",
// deno-lint-ignore prefer-primordials
value: value.valueOf(),
};
} else {
@ -652,14 +695,14 @@ class KvListIterator extends AsyncIterator
let prefix: Deno.KvKey | undefined;
let start: Deno.KvKey | undefined;
let end: Deno.KvKey | undefined;
if ("prefix" in selector && selector.prefix !== undefined) {
prefix = ObjectFreeze([...selector.prefix]);
if (ObjectHasOwn(selector, "prefix") && selector.prefix !== undefined) {
prefix = ObjectFreeze(ArrayPrototypeSlice(selector.prefix));
}
if ("start" in selector && selector.start !== undefined) {
start = ObjectFreeze([...selector.start]);
if (ObjectHasOwn(selector, "start") && selector.start !== undefined) {
start = ObjectFreeze(ArrayPrototypeSlice(selector.start));
}
if ("end" in selector && selector.end !== undefined) {
end = ObjectFreeze([...selector.end]);
if (ObjectHasOwn(selector, "end") && selector.end !== undefined) {
end = ObjectFreeze(ArrayPrototypeSlice(selector.end));
}
if (prefix) {
if (start && end) {
@ -683,7 +726,7 @@ class KvListIterator extends AsyncIterator
);
}
}
Object.freeze(this.#selector);
ObjectFreeze(this.#selector);
this.#pullBatch = pullBatch;
this.#limit = limit;
this.#reverse = reverse;
@ -719,7 +762,7 @@ class KvListIterator extends AsyncIterator
);
// Reverse the batch so we can pop from the end
batch.reverse();
ArrayPrototypeReverse(batch);
this.#entries = batch;
// Last batch, do not attempt to pull more
@ -738,9 +781,9 @@ class KvListIterator extends AsyncIterator
this.#cursorGen = () => {
const selector = this.#selector;
return encodeCursor([
"prefix" in selector ? selector.prefix : null,
"start" in selector ? selector.start : null,
"end" in selector ? selector.end : null,
ObjectHasOwn(selector, "prefix") ? selector.prefix : null,
ObjectHasOwn(selector, "start") ? selector.start : null,
ObjectHasOwn(selector, "end") ? selector.end : null,
], entry.key);
};
this.#count++;
@ -750,7 +793,7 @@ class KvListIterator extends AsyncIterator
};
}
[Symbol.asyncIterator](): AsyncIterator<Deno.KvEntry<unknown>> {
[SymbolAsyncIterator](): AsyncIterator<Deno.KvEntry<unknown>> {
return this;
}
}
@ -761,14 +804,15 @@ async function doAtomicWriteInPlace(
mutations: [Deno.KvKey, string, RawValue | null, number | undefined][],
enqueues: [Uint8Array, number, Deno.KvKey[], number[] | null][],
): Promise<string | null> {
for (const m of mutations) {
const key = m[0];
for (let i = 0; i < mutations.length; ++i) {
const mutation = mutations[i];
const key = mutation[0];
if (
key.length && m[1] === "set" &&
key.length && mutation[1] === "set" &&
key[key.length - 1] === commitVersionstampSymbol
) {
m[0] = key.slice(0, key.length - 1);
m[1] = "setSuffixVersionstampedKey";
mutation[0] = ArrayPrototypeSlice(key, 0, key.length - 1);
mutation[1] = "setSuffixVersionstampedKey";
}
}

View file

@ -23,7 +23,6 @@ const {
Int16Array,
Int32Array,
Int8Array,
isNaN,
MathFloor,
MathFround,
MathMax,
@ -355,7 +354,7 @@ converters.float = (V, prefix, context, _opts) => {
converters["unrestricted float"] = (V, _prefix, _context, _opts) => {
const x = toNumber(V);
if (isNaN(x)) {
if (NumberIsNaN(x)) {
return x;
}

View file

@ -96,13 +96,11 @@ async function dlintPreferPrimordials() {
const execPath = await getPrebuilt("dlint");
const sourceFiles = await getSources(ROOT_PATH, [
"runtime/**/*.js",
"runtime/**/*.ts",
"ext/**/*.js",
"ext/**/*.ts",
":!:ext/**/*.d.ts",
"ext/node/polyfills/*.mjs",
"ext/node/polyfills/*.ts",
":!:ext/node/polyfills/*.d.ts",
"core/*.js",
":!:core/*_test.js",
":!:core/examples/**",
]);
if (!sourceFiles.length) {