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 in | Chrome 151 (Enabled by default) |
|---|---|
| Status | Enabled by default |
| Spec | CSS Font Loading — FontFaceSet |
| Standards position (Firefox) | Shipped/Shipping |
| Standards position (Safari) | Shipped/Shipping |
| ChromeStatus | 5123999844663296 — Remove [LegacyNoInterfaceObject] from FontFaceSet IDL (API record) |
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.
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
| Expression | Chrome 149 and earlier | Chrome 151+ |
|---|---|---|
typeof FontFaceSet | "undefined" | "function" |
window.FontFaceSet | undefined | The FontFaceSet interface constructor |
document.fonts instanceof FontFaceSet | false (throws or returns false) | true |
new FontFaceSet() | TypeError | TypeError (no constructor defined — correct per spec) |
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.
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.
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.
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.
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.
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
| Browser | Support | Notes |
|---|---|---|
| Chrome 151+ | Enabled by default | FontFaceSet now a global property |
| Firefox | Shipped | Already exposed FontFaceSet as a global without constructor |
| Safari | Shipped | Already exposed FontFaceSet as a global (WebKit bug 276794) |
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.
see also
- Chrome Platform Status — Remove [LegacyNoInterfaceObject] from FontFaceSet IDL
- ChromeStatus API record (5123999844663296)
- CSS Font Loading specification — §3 The FontFaceSet Interface
- CSS Font Loading — FontFaceSet interface IDL
- Chromium Issue 477568263 — Remove [LegacyNoInterfaceObject] from FontFaceSet IDL
- MDN Web Docs — FontFaceSet API
- WebKit Bug 276794 — Expose FontFaceSet interface object
- WPT results — css/css-font-loading/historical.html
- Web IDL — LegacyNoInterfaceObject
- WPT GitHub — css/css-font-loading/historical.html