← Chrome 151 reference

v151 · css · fonts · web-idl · interop

Remove [LegacyNoInterfaceObject] from FontFaceSet IDL

Chrome 151 removes an incorrect [LegacyNoInterfaceObject] annotation from the FontFaceSet Web IDL, making FontFaceSet available as a global property in JavaScript. This aligns Chrome with Firefox, Safari, and the CSS Font Loading specification.

at a glance

Shipped inChrome 151 (Enabled by default)
StatusEnabled by default
SpecCSS Font Loading — FontFaceSet
Standards position (Firefox)Shipped/Shipping
Standards position (Safari)Shipped/Shipping
ChromeStatus5123999844663296 — Remove [LegacyNoInterfaceObject] from FontFaceSet IDL (API record)
Source: chromestatus.com/feature/5123999844663296

what changed and why

The Web IDL extended attribute [LegacyNoInterfaceObject] tells the browser not to expose an interface as a named property on the global object. Applied to FontFaceSet, it meant that self.FontFaceSet (and window.FontFaceSet) was undefined in Chrome, and the constructor property was absent from FontFaceSet.prototype.

This deviated from the CSS Font Loading specification, which does not include [LegacyNoInterfaceObject], and from Firefox and Safari where window.FontFaceSet is accessible. Chrome 151 removes the annotation, making the behaviour consistent.

Note on instantiation: because the IDL defines no constructor(), calling new FontFaceSet() continues to throw TypeError: Illegal constructor — this is correct spec-mandated behaviour. FontFaceSet instances are obtained via document.fonts, not by direct construction.

Source: chromestatus feature summary; CSS Font Loading spec

Syntax

Web IDL definition from the CSS Font Loading specification and FontFaceSet interface definition. Chrome 151 removes the non-standard [LegacyNoInterfaceObject] extended attribute, exposing the interface object on Window and Worker global scopes:

[Exposed=(Window,Worker)]
interface FontFaceSet : EventTarget {
};
Source: CSS Font Loading §3 FontFaceSet; Chromium Issue 477568263

what changes

ExpressionChrome 149 and earlierChrome 151+
typeof FontFaceSet"undefined""function"
window.FontFaceSetundefinedThe FontFaceSet interface constructor
document.fonts instanceof FontFaceSetfalse (throws or returns false)true
new FontFaceSet()TypeErrorTypeError (no constructor defined — correct per spec)
Source: chromestatus feature summary

Inputs and parameters

The FontFaceSet interface defines no public constructor operation in Web IDL; calling new FontFaceSet() accepts no arguments and throws an immediate TypeError: Illegal constructor exception. Instance methods on an existing FontFaceSet (such as document.fonts) take standard inputs: add(font) and delete(font) take a FontFace object, while check(font, text) and load(font, text) accept a font string specification and optional text string.

Source: CSS Font Loading §FontFaceSet-interface

Outputs and return values

Accessing the global property window.FontFaceSet or self.FontFaceSet yields the FontFaceSet interface constructor function, for which typeof FontFaceSet returns "function". Evaluating document.fonts instanceof FontFaceSet returns true. On instances, add() returns the FontFaceSet instance for method chaining, delete() returns a boolean indicator of whether the font existed in the set, clear() returns undefined, and ready returns a Promise resolving to the set itself.

Source: MDN FontFaceSet reference

Errors and exceptions

Direct invocation of the constructor via new FontFaceSet() throws a TypeError: Illegal constructor because no constructor is declared in the IDL. Attempting to pass objects that are not FontFace instances to add() or delete() throws a standard TypeError per Web IDL type-checking rules. The historical.html web platform test and WPT test source explicitly assert that calling new FontFaceSet() produces a TypeError.

Source: WPT historical.html results; WPT historical.html repository

Execution context and exposure

Per the Web IDL specification, FontFaceSet carries [Exposed=(Window,Worker)]. It is exposed in both window environments (window.FontFaceSet) and worker environments (self.FontFaceSet within dedicated and shared web workers). It is available in both secure (HTTPS) and non-secure (HTTP) contexts. Instances are exposed to document scripts via document.fonts and to worker scripts via self.fonts.

Source: CSS Font Loading §FontFaceSet-interface

Lifecycle and state transitions

A FontFaceSet instance transitions between loading and loaded statuses as fonts are requested and resolved. The status property reflects this state. When font loading begins, a loading event fires; upon completion, a loadingdone event fires, or a loadingerror event fires if font face loading fails. The ready attribute returns a Promise that fulfills once loading finishes and all font faces are active.

Source: MDN FontFaceSet reference

Examples

// Chrome 151+: FontFaceSet is accessible as a global
console.log(typeof FontFaceSet); // "function"

// Check if document.fonts is a FontFaceSet (now works cross-browser)
console.log(document.fonts instanceof FontFaceSet); // true

// Useful for type-checking / polyfill detection
if (typeof FontFaceSet !== 'undefined') {
  // FontFaceSet interface available
  document.fonts.ready.then(() => {
    console.log('All fonts loaded');
  });
}

// Still works (unchanged) — always use document.fonts, not new FontFaceSet()
const fonts = document.fonts;
fonts.add(new FontFace('MyFont', 'url(myfont.woff2)'));
Source: CSS Font Loading — FontFaceSet

Browser compatibility

BrowserSupportNotes
Chrome 151+Enabled by defaultFontFaceSet now a global property
FirefoxShippedAlready exposed FontFaceSet as a global without constructor
SafariShippedAlready exposed FontFaceSet as a global (WebKit bug 276794)
Source: chromestatus.com/feature/5123999844663296

Security and privacy considerations

Exposing the FontFaceSet interface object on global scopes repairs prototype chain introspection and aligns Chromium with the CSS Font Loading specification and other engines. It exposes no new personal data, fingerprinting surface, cross-origin capabilities, or network channels beyond the font loading mechanisms already accessible through document.fonts.

Source: Chromium Issue 477568263

see also