mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
Answer typeof on builtin import bindings by the export's kind
`const { inspect } = require("util"); typeof inspect` printed "string", as did `import { inspect } from "node:util"` in an ES module and `typeof promises` from `fs`. JavaScript sources represent builtin values without their own lowering as identity tokens (strings), and typeof answered from that representation. typeof on a builtin import binding in a JavaScript source now answers "function" for exported functions and classes and "object" for exported objects; the binding read has no effects. TypeScript sources compile as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
95712ea590
commit
15096a47ed
@@ -678,6 +678,30 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr {
|
||||
if (!sym) {
|
||||
return { kind: "strLit", value: "undefined", type: STRING, loc };
|
||||
}
|
||||
// `const { inspect } = require("util")` / `import { inspect } from
|
||||
// "node:util"`: a binding of a builtin module's exported function,
|
||||
// class or object. JavaScript sources represent such a value without
|
||||
// its own lowering as an identity token (a string), so the operand's
|
||||
// representation cannot answer. Node's answer follows the export's
|
||||
// kind, and the binding read has no effects.
|
||||
const imported = isJsSourceFile(tested.getSourceFile())
|
||||
? lowerer.builtinImportOf(tested)
|
||||
: null;
|
||||
if (
|
||||
imported &&
|
||||
builtinModuleConstOf(lowerer, imported.module, imported.member) === undefined
|
||||
) {
|
||||
const t = lowerer.typeOf(tested);
|
||||
if (
|
||||
lowerer.checker.getCallSignatures(t).length > 0 ||
|
||||
lowerer.checker.getConstructSignatures(t).length > 0
|
||||
) {
|
||||
return { kind: "strLit", value: "function", type: STRING, loc };
|
||||
}
|
||||
if ((t.flags & ts.TypeFlags.Object) !== 0) {
|
||||
return { kind: "strLit", value: "object", type: STRING, loc };
|
||||
}
|
||||
}
|
||||
if (lowerer.isStdlibSymbol(sym)) {
|
||||
const t = lowerer.typeOf(expr.expression);
|
||||
if (
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/6103-typeof-builtin-bindings.cjs"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/6104-typeof-builtin-bindings.mjs"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// typeof on bindings destructured from Node builtin modules: Node answers by
|
||||
// the export's kind ("function" for functions and classes, "object" for
|
||||
// namespace objects), never by how the binding is represented.
|
||||
const { inspect, format, promisify, deprecate, isDeepStrictEqual } = require("util");
|
||||
const { join, resolve } = require("path");
|
||||
const { readFileSync, promises } = require("fs");
|
||||
const { EventEmitter } = require("events");
|
||||
const { createHash } = require("crypto");
|
||||
const util = require("node:util");
|
||||
const { inspect: aliased } = util;
|
||||
console.log(typeof inspect, typeof format, typeof promisify, typeof deprecate, typeof isDeepStrictEqual);
|
||||
console.log(typeof join, typeof resolve, typeof readFileSync, typeof promises);
|
||||
console.log(typeof EventEmitter, typeof createHash, typeof aliased, typeof util.inspect);
|
||||
console.log(typeof inspect === "function" ? "callable" : "not callable");
|
||||
console.log(join("a", "b"), format("%s=%d", "x", 1), inspect({ a: [1, 2] }));
|
||||
@@ -0,0 +1,11 @@
|
||||
// typeof on named, default-destructured and namespace-destructured builtin
|
||||
// bindings in an ES module: Node answers by the export's kind.
|
||||
import util, { inspect as namedInspect, format } from "node:util";
|
||||
import * as path from "node:path";
|
||||
import { createHash } from "node:crypto";
|
||||
import { promises } from "node:fs";
|
||||
const { inspect, promisify } = util;
|
||||
const { join } = path;
|
||||
console.log(typeof inspect, typeof promisify, typeof namedInspect, typeof format);
|
||||
console.log(typeof join, typeof createHash, typeof util.inspect, typeof promises);
|
||||
console.log(namedInspect("s"), format("%d", 2), join("x", "y"));
|
||||
Reference in New Issue
Block a user