Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43,518 changes: 38,977 additions & 4,541 deletions crates/biome_js_type_info/src/generated/global_types.rs

Large diffs are not rendered by default.

322 changes: 175 additions & 147 deletions crates/biome_js_type_info/src/globals.rs

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions crates/biome_js_type_info/src/globals_builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::generated::global_types::MIGRATED_PREDEFINED_IDS;
use crate::{TypeData, TypeStore, globals_ids::NUM_PREDEFINED_TYPES};

use super::{globals::RawGlobalTypes, globals_ids::GlobalTypeId};
Expand Down Expand Up @@ -34,18 +33,6 @@ impl GlobalsResolverBuilder {
*slot = Some(data);
}

/// Skips manual data for IDs owned by the generated module, so codegen remains
/// the source of truth. `MIGRATED_PREDEFINED_IDS` must stay sorted and unique
/// because this lookup uses `binary_search`.
pub(crate) fn set_manual_type_data<F>(&mut self, id: GlobalTypeId, build: F)
where
F: FnOnce() -> TypeData,
{
if MIGRATED_PREDEFINED_IDS.binary_search(&id).is_err() {
self.set_type_data(id, build());
}
}

/// Consumes the builder and produces the immutable raw global table.
pub(crate) fn build(self) -> RawGlobalTypes {
for (index, slot) in self.types.iter().enumerate() {
Expand Down
88 changes: 20 additions & 68 deletions crates/biome_js_type_info/src/globals_ids.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
//! Global IDs consist of a fixed manifest followed by generated declarations.
//! Row position in [`PREDEFINED_ID_ROWS`] is the fixed `TypeId` value, so the
//! manifest is append-only. Generated function IDs follow it in source order.
//!
//! The manifest holds intrinsics that no TypeScript declaration file defines, such
//! as primitive keywords and `typeof` results. Row position in
//! [`PREDEFINED_ID_ROWS`] is the fixed `TypeId` value. Every global declared by the
//! TypeScript standard library follows the manifest, in the order chosen by
//! `just gen-global-types`.

use std::cmp::Ordering;

use crate::{RawTypeId, TypeId};

/// Compile-time guard for manifest length; ordering is checked by `manifest_names_match_id_name_constants`.
const PREDEFINED_TYPE_COUNT: usize = 89;
const PREDEFINED_TYPE_COUNT: usize = 40;

/// Type ID that is known to index the predefined global resolver.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
Expand Down Expand Up @@ -83,13 +87,13 @@ macro_rules! predefined_globals {

/// Number of fixed and generated global type IDs.
pub const NUM_PREDEFINED_TYPES: usize = PREDEFINED_ID_ROWS.len()
+ crate::generated::global_types::VALUE_GLOBALS.len();
+ crate::generated::global_types::GENERATED_GLOBAL_NAMES.len();

/// Returns a string for formatting global IDs in test snapshots.
pub(crate) fn global_type_name(id: TypeId) -> Option<&'static str> {
PREDEFINED_ID_ROWS.get(id.index()).copied().or_else(|| {
let index = id.index().checked_sub(PREDEFINED_ID_ROWS.len())?;
crate::generated::global_types::VALUE_GLOBALS.get(index).map(|(name, _)| *name)
crate::generated::global_types::GENERATED_GLOBAL_NAMES.get(index).copied()
})
}
};
Expand Down Expand Up @@ -120,28 +124,20 @@ predefined_globals! {
(UNDEFINED_ID, UNDEFINED_ID_NAME, UNDEFINED_ID_GLOBAL_TYPE_ID, GLOBAL_UNDEFINED_ID, "undefined", Sentinel),
(VOID_ID, VOID_ID_NAME, VOID_ID_GLOBAL_TYPE_ID, GLOBAL_VOID_ID, "void", Sentinel),
(CONDITIONAL_ID, CONDITIONAL_ID_NAME, CONDITIONAL_ID_GLOBAL_TYPE_ID, GLOBAL_CONDITIONAL_ID, "conditional", Sentinel),
(NUMBER_ID, NUMBER_ID_NAME, NUMBER_ID_GLOBAL_TYPE_ID, GLOBAL_NUMBER_ID, "number", Primitive),
(STRING_ID, STRING_ID_NAME, STRING_ID_GLOBAL_TYPE_ID, GLOBAL_STRING_ID, "string", Primitive),
(NUMBER_KEYWORD_ID, NUMBER_KEYWORD_ID_NAME, NUMBER_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_NUMBER_KEYWORD_ID, "number", Primitive),
(STRING_KEYWORD_ID, STRING_KEYWORD_ID_NAME, STRING_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_STRING_KEYWORD_ID, "string", Primitive),
(BOOLEAN_KEYWORD_ID, BOOLEAN_KEYWORD_ID_NAME, BOOLEAN_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_BOOLEAN_KEYWORD_ID, "boolean", Primitive),
(BIGINT_KEYWORD_ID, BIGINT_KEYWORD_ID_NAME, BIGINT_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_BIGINT_KEYWORD_ID, "bigint", Primitive),
(SYMBOL_KEYWORD_ID, SYMBOL_KEYWORD_ID_NAME, SYMBOL_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_KEYWORD_ID, "symbol", Primitive),
(NULL_KEYWORD_ID, NULL_KEYWORD_ID_NAME, NULL_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_NULL_KEYWORD_ID, "null", Primitive),
(ANY_KEYWORD_ID, ANY_KEYWORD_ID_NAME, ANY_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_ANY_KEYWORD_ID, "any", Primitive),
(NEVER_KEYWORD_ID, NEVER_KEYWORD_ID_NAME, NEVER_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_NEVER_KEYWORD_ID, "never", Primitive),
(OBJECT_KEYWORD_ID, OBJECT_KEYWORD_ID_NAME, OBJECT_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_OBJECT_KEYWORD_ID, "object", Primitive),
(UNKNOWN_KEYWORD_ID, UNKNOWN_KEYWORD_ID_NAME, UNKNOWN_KEYWORD_ID_GLOBAL_TYPE_ID, GLOBAL_UNKNOWN_KEYWORD_ID, "unknown", Primitive),
(INSTANCEOF_ARRAY_T_ID, INSTANCEOF_ARRAY_T_ID_NAME, INSTANCEOF_ARRAY_T_ID_GLOBAL_TYPE_ID, GLOBAL_INSTANCEOF_ARRAY_T_ID, "instanceof Array<T>", Helper),
(INSTANCEOF_ARRAY_U_ID, INSTANCEOF_ARRAY_U_ID_NAME, INSTANCEOF_ARRAY_U_ID_GLOBAL_TYPE_ID, GLOBAL_INSTANCEOF_ARRAY_U_ID, "instanceof Array<U>", Helper),
(ARRAY_ID, ARRAY_ID_NAME, ARRAY_ID_GLOBAL_TYPE_ID, GLOBAL_ARRAY_ID, "Array", ManualGlobal),
(ARRAY_FILTER_ID, ARRAY_FILTER_ID_NAME, ARRAY_FILTER_ID_GLOBAL_TYPE_ID, GLOBAL_ARRAY_FILTER_ID, "Array.prototype.filter", ManualSynthetic),
(ARRAY_FOREACH_ID, ARRAY_FOREACH_ID_NAME, ARRAY_FOREACH_ID_GLOBAL_TYPE_ID, GLOBAL_ARRAY_FOREACH_ID, "Array.prototype.forEach", ManualSynthetic),
(ARRAY_MAP_ID, ARRAY_MAP_ID_NAME, ARRAY_MAP_ID_GLOBAL_TYPE_ID, GLOBAL_ARRAY_MAP_ID, "Array.prototype.map", ManualSynthetic),
(GLOBAL_ID, GLOBAL_ID_NAME, GLOBAL_ID_GLOBAL_TYPE_ID, GLOBAL_GLOBAL_ID, "globalThis", Helper),
(INSTANCEOF_PROMISE_ID, INSTANCEOF_PROMISE_ID_NAME, INSTANCEOF_PROMISE_ID_GLOBAL_TYPE_ID, GLOBAL_INSTANCEOF_PROMISE_ID, "instanceof Promise", Helper),
(PROMISE_ID, PROMISE_ID_NAME, PROMISE_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_ID, "Promise", ManualGlobal),
(PROMISE_CONSTRUCTOR_ID, PROMISE_CONSTRUCTOR_ID_NAME, PROMISE_CONSTRUCTOR_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_CONSTRUCTOR_ID, "Promise.constructor", ManualSynthetic),
(PROMISE_CATCH_ID, PROMISE_CATCH_ID_NAME, PROMISE_CATCH_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_CATCH_ID, "Promise.prototype.catch", ManualSynthetic),
(PROMISE_FINALLY_ID, PROMISE_FINALLY_ID_NAME, PROMISE_FINALLY_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_FINALLY_ID, "Promise.prototype.finally", ManualSynthetic),
(PROMISE_THEN_ID, PROMISE_THEN_ID_NAME, PROMISE_THEN_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_THEN_ID, "Promise.prototype.then", ManualSynthetic),
(PROMISE_ALL_ID, PROMISE_ALL_ID_NAME, PROMISE_ALL_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_ALL_ID, "Promise.all", ManualSynthetic),
(PROMISE_ALL_SETTLED_ID, PROMISE_ALL_SETTLED_ID_NAME, PROMISE_ALL_SETTLED_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_ALL_SETTLED_ID, "Promise.allSettled", ManualSynthetic),
(PROMISE_ANY_ID, PROMISE_ANY_ID_NAME, PROMISE_ANY_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_ANY_ID, "Promise.any", ManualSynthetic),
(PROMISE_RACE_ID, PROMISE_RACE_ID_NAME, PROMISE_RACE_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_RACE_ID, "Promise.race", ManualSynthetic),
(PROMISE_REJECT_ID, PROMISE_REJECT_ID_NAME, PROMISE_REJECT_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_REJECT_ID, "Promise.reject", ManualSynthetic),
(PROMISE_RESOLVE_ID, PROMISE_RESOLVE_ID_NAME, PROMISE_RESOLVE_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_RESOLVE_ID, "Promise.resolve", ManualSynthetic),
(PROMISE_TRY_ID, PROMISE_TRY_ID_NAME, PROMISE_TRY_ID_GLOBAL_TYPE_ID, GLOBAL_PROMISE_TRY_ID, "Promise.try", ManualSynthetic),
(BIGINT_STRING_LITERAL_ID, BIGINT_STRING_LITERAL_ID_NAME, BIGINT_STRING_LITERAL_ID_GLOBAL_TYPE_ID, GLOBAL_BIGINT_STRING_LITERAL_ID, "\"bigint\"", Helper),
(BOOLEAN_STRING_LITERAL_ID, BOOLEAN_STRING_LITERAL_ID_NAME, BOOLEAN_STRING_LITERAL_ID_GLOBAL_TYPE_ID, GLOBAL_BOOLEAN_STRING_LITERAL_ID, "\"boolean\"", Helper),
(FUNCTION_STRING_LITERAL_ID, FUNCTION_STRING_LITERAL_ID_NAME, FUNCTION_STRING_LITERAL_ID_GLOBAL_TYPE_ID, GLOBAL_FUNCTION_STRING_LITERAL_ID, "\"function\"", Helper),
Expand All @@ -160,55 +156,11 @@ predefined_globals! {
(MAP_CALLBACK_ID, MAP_CALLBACK_ID_NAME, MAP_CALLBACK_ID_GLOBAL_TYPE_ID, GLOBAL_MAP_CALLBACK_ID, "<U>(item: T) => U", Helper),
(VOID_CALLBACK_ID, VOID_CALLBACK_ID_NAME, VOID_CALLBACK_ID_GLOBAL_TYPE_ID, GLOBAL_VOID_CALLBACK_ID, "() => void", Helper),
(FETCH_ID, FETCH_ID_NAME, FETCH_ID_GLOBAL_TYPE_ID, _, "fetch", HostManual),
(INSTANCEOF_REGEXP_ID, INSTANCEOF_REGEXP_ID_NAME, INSTANCEOF_REGEXP_ID_GLOBAL_TYPE_ID, _, "instanceof RegExp", Helper),
(REGEXP_ID, REGEXP_ID_NAME, REGEXP_ID_GLOBAL_TYPE_ID, GLOBAL_REGEXP_ID, "RegExp", ManualGlobal),
(REGEXP_EXEC_ID, REGEXP_EXEC_ID_NAME, REGEXP_EXEC_ID_GLOBAL_TYPE_ID, GLOBAL_REGEXP_EXEC_ID, "RegExp.exec", ManualSynthetic),
(INSTANCEOF_REG_EXP_ID, INSTANCEOF_REG_EXP_ID_NAME, INSTANCEOF_REG_EXP_ID_GLOBAL_TYPE_ID, _, "instanceof RegExp", Helper),
(INSTANCEOF_SYMBOL_ID, INSTANCEOF_SYMBOL_ID_NAME, INSTANCEOF_SYMBOL_ID_GLOBAL_TYPE_ID, _, "instanceof Symbol", Helper),
(SYMBOL_ID, SYMBOL_ID_NAME, SYMBOL_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_ID, "Symbol", ManualGlobal),
(SYMBOL_DISPOSE_ID, SYMBOL_DISPOSE_ID_NAME, SYMBOL_DISPOSE_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_DISPOSE_ID, "Symbol.dispose", ManualSynthetic),
(SYMBOL_ASYNC_DISPOSE_ID, SYMBOL_ASYNC_DISPOSE_ID_NAME, SYMBOL_ASYNC_DISPOSE_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_ASYNC_DISPOSE_ID, "Symbol.asyncDispose", ManualSynthetic),
(DISPOSABLE_ID, DISPOSABLE_ID_NAME, DISPOSABLE_ID_GLOBAL_TYPE_ID, GLOBAL_DISPOSABLE_ID, "Disposable", ManualGlobal),
(DISPOSABLE_DISPOSE_ID, DISPOSABLE_DISPOSE_ID_NAME, DISPOSABLE_DISPOSE_ID_GLOBAL_TYPE_ID, GLOBAL_DISPOSABLE_DISPOSE_ID, "Disposable[Symbol.dispose]", ManualSynthetic),
(ASYNC_DISPOSABLE_ID, ASYNC_DISPOSABLE_ID_NAME, ASYNC_DISPOSABLE_ID_GLOBAL_TYPE_ID, _, "AsyncDisposable", ManualGlobal),
(ASYNC_DISPOSABLE_ASYNC_DISPOSE_ID, ASYNC_DISPOSABLE_ASYNC_DISPOSE_ID_NAME, ASYNC_DISPOSABLE_ASYNC_DISPOSE_ID_GLOBAL_TYPE_ID, GLOBAL_ASYNC_DISPOSABLE_ASYNC_DISPOSE_ID,
"AsyncDisposable[Symbol.asyncDispose]",
ManualSynthetic,
),
(INSTANCEOF_DATE_ID, INSTANCEOF_DATE_ID_NAME, INSTANCEOF_DATE_ID_GLOBAL_TYPE_ID, _, "instanceof Date", Helper),
(DATE_ID, DATE_ID_NAME, DATE_ID_GLOBAL_TYPE_ID, GLOBAL_DATE_ID, "Date", ManualGlobal),
(INSTANCEOF_MAP_ID, INSTANCEOF_MAP_ID_NAME, INSTANCEOF_MAP_ID_GLOBAL_TYPE_ID, _, "instanceof Map", Helper),
(MAP_ID, MAP_ID_NAME, MAP_ID_GLOBAL_TYPE_ID, GLOBAL_MAP_ID, "Map", ManualGlobal),
(INSTANCEOF_SET_ID, INSTANCEOF_SET_ID_NAME, INSTANCEOF_SET_ID_GLOBAL_TYPE_ID, _, "instanceof Set", Helper),
(SET_ID, SET_ID_NAME, SET_ID_GLOBAL_TYPE_ID, GLOBAL_SET_ID, "Set", ManualGlobal),
(INSTANCEOF_WEAK_MAP_ID, INSTANCEOF_WEAK_MAP_ID_NAME, INSTANCEOF_WEAK_MAP_ID_GLOBAL_TYPE_ID, _, "instanceof WeakMap", Helper),
(WEAK_MAP_ID, WEAK_MAP_ID_NAME, WEAK_MAP_ID_GLOBAL_TYPE_ID, GLOBAL_WEAK_MAP_ID, "WeakMap", ManualGlobal),
(INSTANCEOF_ERROR_ID, INSTANCEOF_ERROR_ID_NAME, INSTANCEOF_ERROR_ID_GLOBAL_TYPE_ID, GLOBAL_INSTANCEOF_ERROR_ID, "instanceof Error", Helper),
(ERROR_ID, ERROR_ID_NAME, ERROR_ID_GLOBAL_TYPE_ID, GLOBAL_ERROR_ID, "Error", ManualGlobal),
(BOOLEAN_ID, BOOLEAN_ID_NAME, BOOLEAN_ID_GLOBAL_TYPE_ID, _, "boolean", Primitive),
(ERROR_CONSTRUCTOR_ID, ERROR_CONSTRUCTOR_ID_NAME, ERROR_CONSTRUCTOR_ID_GLOBAL_TYPE_ID, GLOBAL_ERROR_CONSTRUCTOR_ID, "Error.constructor", ManualSynthetic),
(ERROR_CALL_ID, ERROR_CALL_ID_NAME, ERROR_CALL_ID_GLOBAL_TYPE_ID, GLOBAL_ERROR_CALL_ID, "Error.call", ManualSynthetic),
(ITERATOR_YIELD_RESULT_ID, ITERATOR_YIELD_RESULT_ID_NAME, ITERATOR_YIELD_RESULT_ID_GLOBAL_TYPE_ID, GLOBAL_ITERATOR_YIELD_RESULT_ID, "IteratorYieldResult", Helper),
(ITERATOR_RETURN_RESULT_ID, ITERATOR_RETURN_RESULT_ID_NAME, ITERATOR_RETURN_RESULT_ID_GLOBAL_TYPE_ID, GLOBAL_ITERATOR_RETURN_RESULT_ID, "IteratorReturnResult", Helper),
(ITERATOR_RESULT_ID, ITERATOR_RESULT_ID_NAME, ITERATOR_RESULT_ID_GLOBAL_TYPE_ID, GLOBAL_ITERATOR_RESULT_ID, "IteratorResult", Helper),
(ITERATOR_ID, ITERATOR_ID_NAME, ITERATOR_ID_GLOBAL_TYPE_ID, GLOBAL_ITERATOR_ID, "Iterator", Helper),
(MATH_ID, MATH_ID_NAME, MATH_ID_GLOBAL_TYPE_ID, _, "Math", ManualGlobal),
(ITERABLE_ID, ITERABLE_ID_NAME, ITERABLE_ID_GLOBAL_TYPE_ID, GLOBAL_ITERABLE_ID, "Iterable", Helper),
(SYMBOL_ITERATOR_ID, SYMBOL_ITERATOR_ID_NAME, SYMBOL_ITERATOR_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_ITERATOR_ID, "Symbol.iterator", ManualSynthetic),
(REGEXP_EXEC_ARRAY_ID, REGEXP_EXEC_ARRAY_ID_NAME, REGEXP_EXEC_ARRAY_ID_GLOBAL_TYPE_ID, GLOBAL_REGEXP_EXEC_ARRAY_ID, "RegExpExecArray", Helper),
(ARRAY_LIKE_ID, ARRAY_LIKE_ID_NAME, ARRAY_LIKE_ID_GLOBAL_TYPE_ID, GLOBAL_ARRAY_LIKE_ID, "ArrayLike", Helper),
(SYMBOL_TO_STRING_TAG_ID, SYMBOL_TO_STRING_TAG_ID_NAME, SYMBOL_TO_STRING_TAG_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_TO_STRING_TAG_ID, "Symbol.toStringTag", ManualSynthetic),
(SYMBOL_TO_PRIMITIVE_ID, SYMBOL_TO_PRIMITIVE_ID_NAME, SYMBOL_TO_PRIMITIVE_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_TO_PRIMITIVE_ID, "Symbol.toPrimitive", ManualSynthetic),
(SYMBOL_MATCH_ID, SYMBOL_MATCH_ID_NAME, SYMBOL_MATCH_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_MATCH_ID, "Symbol.match", ManualSynthetic),
(SYMBOL_REPLACE_ID, SYMBOL_REPLACE_ID_NAME, SYMBOL_REPLACE_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_REPLACE_ID, "Symbol.replace", ManualSynthetic),
(SYMBOL_SEARCH_ID, SYMBOL_SEARCH_ID_NAME, SYMBOL_SEARCH_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_SEARCH_ID, "Symbol.search", ManualSynthetic),
(SYMBOL_SPLIT_ID, SYMBOL_SPLIT_ID_NAME, SYMBOL_SPLIT_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_SPLIT_ID, "Symbol.split", ManualSynthetic),
(SYMBOL_SPECIES_ID, SYMBOL_SPECIES_ID_NAME, SYMBOL_SPECIES_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_SPECIES_ID, "Symbol.species", ManualSynthetic),
(SYMBOL_HAS_INSTANCE_ID, SYMBOL_HAS_INSTANCE_ID_NAME, SYMBOL_HAS_INSTANCE_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_HAS_INSTANCE_ID, "Symbol.hasInstance", ManualSynthetic),
(SYMBOL_UNSCOPABLES_ID, SYMBOL_UNSCOPABLES_ID_NAME, SYMBOL_UNSCOPABLES_ID_GLOBAL_TYPE_ID, GLOBAL_SYMBOL_UNSCOPABLES_ID, "Symbol.unscopables", ManualSynthetic),
(REGEXP_MATCH_ARRAY_ID, REGEXP_MATCH_ARRAY_ID_NAME, REGEXP_MATCH_ARRAY_ID_GLOBAL_TYPE_ID, GLOBAL_REGEXP_MATCH_ARRAY_ID, "RegExpMatchArray", Helper),
(ITERATOR_OBJECT_ID, ITERATOR_OBJECT_ID_NAME, ITERATOR_OBJECT_ID_GLOBAL_TYPE_ID, GLOBAL_ITERATOR_OBJECT_ID, "IteratorObject", Helper),
(MAP_ITERATOR_ID, MAP_ITERATOR_ID_NAME, MAP_ITERATOR_ID_GLOBAL_TYPE_ID, GLOBAL_MAP_ITERATOR_ID, "MapIterator", Helper),
(SET_ITERATOR_ID, SET_ITERATOR_ID_NAME, SET_ITERATOR_ID_GLOBAL_TYPE_ID, GLOBAL_SET_ITERATOR_ID, "SetIterator", Helper),
(BUILTIN_ITERATOR_RETURN_ID, BUILTIN_ITERATOR_RETURN_ID_NAME, BUILTIN_ITERATOR_RETURN_ID_GLOBAL_TYPE_ID, GLOBAL_BUILTIN_ITERATOR_RETURN_ID, "BuiltinIteratorReturn", Helper),
(INTL_ID, INTL_ID_NAME, INTL_ID_GLOBAL_TYPE_ID, _, "Intl", ManualGlobal),
}
6 changes: 6 additions & 0 deletions crates/biome_js_type_info/src/inferred_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,12 @@ impl<'db> InferredType<'db> {
TypeData::Intersection(intersection) => {
pending.extend(intersection.types(self.db).iter().copied());
}
TypeData::IndexedAccess(access) => {
let Some(types) = access.keyof_property_types(self.db) else {
return ConditionalType::Unknown;
};
pending.extend(types);
}
TypeData::MergedReference(reference) => pending.extend(
[
reference.ty(self.db),
Expand Down
54 changes: 45 additions & 9 deletions crates/biome_js_type_info/src/interned_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ use std::iter::FusedIterator;
use crate::{
ScopeId,
builders::{IntersectionBuilder, UnionBuilder},
globals_ids::{
generated::global_types::ids::{
ARRAY_ID_GLOBAL_TYPE_ID, ASYNC_DISPOSABLE_ID_GLOBAL_TYPE_ID, DATE_ID_GLOBAL_TYPE_ID,
DISPOSABLE_ID_GLOBAL_TYPE_ID, ERROR_ID_GLOBAL_TYPE_ID, GlobalTypeId, MAP_ID_GLOBAL_TYPE_ID,
PROMISE_ID_GLOBAL_TYPE_ID, REGEXP_ID_GLOBAL_TYPE_ID, SET_ID_GLOBAL_TYPE_ID,
DISPOSABLE_ID_GLOBAL_TYPE_ID, ERROR_ID_GLOBAL_TYPE_ID, MAP_ID_GLOBAL_TYPE_ID,
PROMISE_ID_GLOBAL_TYPE_ID, REG_EXP_ID_GLOBAL_TYPE_ID, SET_ID_GLOBAL_TYPE_ID,
SYMBOL_ID_GLOBAL_TYPE_ID, WEAK_MAP_ID_GLOBAL_TYPE_ID,
},
globals_ids::GlobalTypeId,
literal::{BooleanLiteral, NumberLiteral, RegexpLiteral, StringLiteral},
type_data as raw,
};
Expand All @@ -44,11 +45,7 @@ pub fn well_known_symbol_name(ty: TypeData) -> Option<Text> {
}

pub fn well_known_symbol_type<'db>(member_name: &str) -> Option<TypeData<'db>> {
crate::globals_ids::PREDEFINED_ID_ROWS
.iter()
.position(|name| name.strip_prefix("Symbol.") == Some(member_name))
.and_then(|index| GlobalTypeId::try_from_type_id(raw::TypeId::new(index)))
.map(TypeData::GlobalType)
crate::global_type_id_for_value(&format!("Symbol.{member_name}")).map(TypeData::GlobalType)
}

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Update)]
Expand Down Expand Up @@ -933,7 +930,7 @@ impl<'db> TypeData<'db> {
}

pub const fn regexp_class() -> Self {
Self::GlobalType(REGEXP_ID_GLOBAL_TYPE_ID)
Self::GlobalType(REG_EXP_ID_GLOBAL_TYPE_ID)
}

pub const fn set_class() -> Self {
Expand Down Expand Up @@ -2524,6 +2521,45 @@ pub struct InternedIndexedAccessType<'db> {
pub index: TypeData<'db>,
}

impl<'db> InternedIndexedAccessType<'db> {
/// Evaluates `T[keyof T]` to the types of `T`'s properties.
///
/// Returns `None` for other indexed accesses, and when `T` has members other
/// than required properties, because those would contribute types that this
/// evaluation does not model.
///
/// ```ts
/// interface WeakKeyTypes { object: object; symbol: symbol }
/// type WeakKey = WeakKeyTypes[keyof WeakKeyTypes]; // object | symbol
/// ```
pub fn keyof_property_types(self, db: &'db dyn TypeDb) -> Option<Box<[TypeData<'db>]>> {
let object = self.object(db);
let TypeData::TypeOperator(operator) = self.index(db) else {
return None;
};
if operator.operator(db) != raw::TypeOperator::Keyof || operator.ty(db) != object {
return None;
}
let target = match object {
TypeData::InstanceOf(instance) if instance.type_parameters(db).is_empty() => {
instance.ty(db)
}
object => object,
};
let members = match target.expand_canonical_global(db) {
TypeData::Interface(interface) if interface.extends(db).is_empty() => {
interface.members(db).as_ref()
}
TypeData::Object(object) => object.members(db).as_ref(),
_ => return None,
};
members
.iter()
.map(|member| matches!(member.kind, TypeMemberKind::Named(_)).then_some(member.ty))
.collect()
}
}

#[salsa::interned]
#[derive(Debug)]
pub struct InternedTypeofExpression<'db> {
Expand Down
Loading
Loading