Repository: denoland/deno_core
Pull request #695 (2024-04-11 14:25:31)

chore: add some code that was crashing deno


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 09bdcae..e845e2f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -487,9 +487,9 @@ dependencies = [
 
 [[package]]
 name = "deno_ast"
-version = "0.35.2"
+version = "0.35.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebb7284111ad08453aab0d07caf32564de730c9a77f2b94a4b69207b15cf1f2d"
+checksum = "f340bc18a3c351cb4af21e56a8af13cdcc08ff7616799429c745bce26fea6385"
 dependencies = [
  "anyhow",
  "base64",
@@ -2050,9 +2050,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_codegen"
-version = "0.148.14"
+version = "0.148.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e318142ff1297c1d3d8f230b4f3eda8454d1420341fb098a9d9edbc373ef3c"
+checksum = "5206067d7c5034e4e19e71ebce270081594eb726c108d0a0a026f7ecbb6f8abd"
 dependencies = [
  "memchr",
  "num-bigint",
@@ -2095,9 +2095,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_parser"
-version = "0.143.12"
+version = "0.143.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6fc7ab256f83a9491b37a510dd1cba9d81bb306faf3cff1dacdbc897fa4869f"
+checksum = "5354a20ab66c2ec5001982271b6e7c750b7fca3409888ab9703ae3d3c845fed4"
 dependencies = [
  "either",
  "new_debug_unreachable",
@@ -2281,9 +2281,9 @@ dependencies = [
 
 [[package]]
 name = "swc_visit"
-version = "0.5.12"
+version = "0.5.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dcfe07ffcd4360d6bf69d75819ccf6c6db852dfbf0f35dd65e9296a2b25c070"
+checksum = "0263be55289abfe9c877ffef83d877b5bdfac036ffe2de793f48f5e47e41dbae"
 dependencies = [
  "either",
  "swc_visit_macros",
diff --git a/Cargo.toml b/Cargo.toml
index f5b9107..9cc9cd8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,7 @@ deno_ops = { version = "0.149.0", path = "./ops" }
 serde_v8 = { version = "0.182.0", path = "./serde_v8" }
 
 v8 = { version = "0.89.0", default-features = false }
-deno_ast = { version = "=0.35.2", features = ["transpiling"] }
+deno_ast = { version = "=0.35.3", features = ["transpiling"] }
 deno_unsync = "0.3.2"
 deno_core_icudata = "0.0.73"
 


Test patch:
diff --git a/testing/integration/ts_types/decorator.ts b/testing/integration/ts_types/decorator.ts
new file mode 100644
index 0000000..d0b9181
--- /dev/null
+++ b/testing/integration/ts_types/decorator.ts
@@ -0,0 +1,18 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+function logged(value, { kind, name }) {
+  if (kind === "method" || kind === "getter" || kind === "setter") {
+    return function (...args) {
+      console.log(`starting ${name} with arguments ${args.join(", ")}`);
+      const ret = value.call(this, ...args);
+      console.log(`ending ${name}`);
+      return ret;
+    };
+  }
+}
+
+class C {
+  @logged
+  set x(arg) {}
+}
+
+new C().x = 1;
diff --git a/testing/integration/ts_types/ts_types.out b/testing/integration/ts_types/ts_types.out
new file mode 100644
index 0000000..d6679f8
--- /dev/null
+++ b/testing/integration/ts_types/ts_types.out
@@ -0,0 +1,4 @@
+starting x with arguments 1
+ending x
+{}
+{}
diff --git a/testing/integration/ts_types/ts_types.ts b/testing/integration/ts_types/ts_types.ts
new file mode 100644
index 0000000..ab0ac3b
--- /dev/null
+++ b/testing/integration/ts_types/ts_types.ts
@@ -0,0 +1,5 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+import * as which from "./which.ts";
+import * as decorator from "./decorator.ts";
+console.log(which);
+console.log(decorator);
diff --git a/testing/integration/ts_types/which.ts b/testing/integration/ts_types/which.ts
new file mode 100644
index 0000000..656be46
--- /dev/null
+++ b/testing/integration/ts_types/which.ts
@@ -0,0 +1,205 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+// https://github.com/dsherret/deno-which/blob/main/mod.ts
+
+/**
+ * This file triggered a crash in Deno.
+ */
+
+declare namespace Deno {
+  class FileInfo {
+    name: string;
+    isFile: boolean;
+  }
+  function stat(...any);
+  function statSync(...any);
+  namespace env {
+    function get(string);
+  }
+  namespace errors {
+    class PermissionDenied {}
+  }
+  namespace build {
+    const os: string;
+  }
+}
+
+export interface Environment {
+  /** Gets an environment variable. */
+  env(key: string): string | undefined;
+  /** Resolves the `Deno.FileInfo` for the specified
+   * path following symlinks.
+   */
+  stat(filePath: string): Promise<Pick<Deno.FileInfo, "isFile">>;
+  /** Synchronously resolves the `Deno.FileInfo` for
+   * the specified path following symlinks.
+   */
+  statSync(filePath: string): Pick<Deno.FileInfo, "isFile">;
+  /** Gets the current operating system. */
+  os: typeof Deno.build.os;
+}
+
+export class RealEnvironment implements Environment {
+  env(key: string): string | undefined {
+    return Deno.env.get(key);
+  }
+
+  stat(path: string): Promise<Pick<Deno.FileInfo, "isFile">> {
+    return Deno.stat(path);
+  }
+
+  statSync(path: string): Pick<Deno.FileInfo, "isFile"> {
+    return Deno.statSync(path);
+  }
+
+  get os(): typeof Deno.build.os {
+    return Deno.build.os;
+  }
+}
+
+/** Finds the path to the specified command asynchronously. */
+export async function which(
+  command: string,
+  environment: Omit<Environment, "statSync"> = new RealEnvironment(),
+): Promise<string | undefined> {
+  const systemInfo = getSystemInfo(command, environment);
+  if (systemInfo == null) {
+    return undefined;
+  }
+
+  for (const pathItem of systemInfo.pathItems) {
+    const filePath = pathItem + command;
+    if (systemInfo.pathExts) {
+      for (const pathExt of systemInfo.pathExts) {
+        const filePath = pathItem + command + pathExt;
+        if (await pathMatches(environment, filePath)) {
+          return filePath;
+        }
+      }
+    } else {
+      if (await pathMatches(environment, filePath)) {
+        return filePath;
+      }
+    }
+  }
+
+  return undefined;
+}
+
+async function pathMatches(
+  environment: Omit<Environment, "statSync">,
+  path: string,
+): Promise<boolean> {
+  try {
+    const result = await environment.stat(path);
+    return result.isFile;
+  } catch (err) {
+    if (err instanceof Deno.errors.PermissionDenied) {
+      throw err;
+    }
+    return false;
+  }
+}
+
+/** Finds the path to the specified command synchronously. */
+export function whichSync(
+  command: string,
+  environment: Omit<Environment, "stat"> = new RealEnvironment(),
+): string | undefined {
+  const systemInfo = getSystemInfo(command, environment);
+  if (systemInfo == null) {
+    return undefined;
+  }
+
+  for (const pathItem of systemInfo.pathItems) {
+    const filePath = pathItem + command;
+    if (pathMatchesSync(environment, filePath)) {
+      return filePath;
+    }
+    if (systemInfo.pathExts) {
+      for (const pathExt of systemInfo.pathExts) {
+        const filePath = pathItem + command + pathExt;
+        if (pathMatchesSync(environment, filePath)) {
+          return filePath;
+        }
+      }
+    }
+  }
+
+  return undefined;
+}
+
+function pathMatchesSync(
+  environment: Omit<Environment, "stat">,
+  path: string,
+): boolean {
+  try {
+    const result = environment.statSync(path);
+    return result.isFile;
+  } catch (err) {
+    if (err instanceof Deno.errors.PermissionDenied) {
+      throw err;
+    }
+    return false;
+  }
+}
+
+interface SystemInfo {
+  pathItems: string[];
+  pathExts: string[] | undefined;
+  isNameMatch: (a: string, b: string) => boolean;
+}
+
+function getSystemInfo(
+  command: string,
+  environment: Omit<Environment, "stat" | "statSync">,
+): SystemInfo | undefined {
+  const isWindows = environment.os === "windows";
+  const envValueSeparator = isWindows ? ";" : ":";
+  const path = environment.env("PATH");
+  const pathSeparator = isWindows ? "\\" : "/";
+  if (path == null) {
+    return undefined;
+  }
+
+  return {
+    pathItems: splitEnvValue(path).map((item) => normalizeDir(item)),
+    pathExts: getPathExts(),
+    isNameMatch: isWindows
+      ? (a, b) => a.toLowerCase() === b.toLowerCase()
+      : (a, b) => a === b,
+  };
+
+  function getPathExts() {
+    if (!isWindows) {
+      return undefined;
+    }
+
+    const pathExtText = environment.env("PATHEXT") ?? ".EXE;.CMD;.BAT;.COM";
+    const pathExts = splitEnvValue(pathExtText);
+    const lowerCaseCommand = command.toLowerCase();
+
+    for (const pathExt of pathExts) {
+      // Do not use the pathExts if someone has provided a command
+      // that ends with the extenion of an executable extension
+      if (lowerCaseCommand.endsWith(pathExt.toLowerCase())) {
+        return undefined;
+      }
+    }
+
+    return pathExts;
+  }
+
+  function splitEnvValue(value: string) {
+    return value
+      .split(envValueSeparator)
+      .map((item) => item.trim())
+      .filter((item) => item.length > 0);
+  }
+
+  function normalizeDir(dirPath: string) {
+    if (!dirPath.endsWith(pathSeparator)) {
+      dirPath += pathSeparator;
+    }
+    return dirPath;
+  }
+}
diff --git a/testing/lib.rs b/testing/lib.rs
index 8d61095..bc0222c 100644
--- a/testing/lib.rs
+++ b/testing/lib.rs
@@ -64,6 +64,7 @@ integration_test!(
   timer_ref,
   timer_ref_and_cancel,
   timer_many,
+  ts_types,
   worker_spawn,
   worker_terminate,
   worker_terminate_op,