Skip to content

[lexical-code-prism] Bug Fix: read the language maps as own properties - #8981

Merged
etrepum merged 1 commit into
facebook:mainfrom
luantaraschi:fix/code-language-prototype-lookup
Aug 9, 2026
Merged

[lexical-code-prism] Bug Fix: read the language maps as own properties#8981
etrepum merged 1 commit into
facebook:mainfrom
luantaraschi:fix/code-language-prototype-lookup

Conversation

@luantaraschi

Copy link
Copy Markdown
Contributor

Description

normalizeCodeLanguage and getLanguageFriendlyName are declared as returning a string, and for a handful of language names they return a function instead.

Both read their map with a plain index, and both maps are object literals:

CODE_LANGUAGE_MAP[lang] || lang
CODE_LANGUAGE_FRIENDLY_NAME_MAP[_lang] || _lang

So a language whose name matches a member of Object.prototype resolves to the inherited value rather than falling through to lang:

normalizeCodeLanguage('constructor')     -> function Object
normalizeCodeLanguage('toString')        -> function toString
normalizeCodeLanguage('valueOf')         -> function valueOf
normalizeCodeLanguage('hasOwnProperty')  -> function hasOwnProperty
normalizeCodeLanguage('__proto__')       -> Object.prototype

The language of a code block is whatever the document carries, so the name is not ours to choose. The markdown transformer reads the info string of a fence and hands it straight to $createCodeNode:

const language = startMatch[2] || undefined;
...
codeBlockNode = $createCodeNode(language);

so importing ```constructor is enough to reach it. From there the playground's CodeActionMenuPlugin renders getLanguageFriendlyName(lang) as the label and passes normalizeCodeLanguage(...) to canBePrettier, both of which now receive a function.

Worth mentioning because it is the thing that convinced me the fix belongs here rather than at the call sites: the sibling facade already gets this right. normalizeCodeLanguage in @lexical/code-shiki looks the name up with bundledLanguagesInfo.find(...), an array search, so no name can reach a prototype member.

I kept both maps as plain objects, since they are exported and swapping them for a Map would be a breaking change for anyone reading or spreading them. The lookups go through a small helper that only accepts own properties, which leaves the || fallback behaving exactly as before for every language that is actually in the map.

Test plan

Two tests added to CodePrismLanguageOptions.test.ts: one walks the six names above through both functions, and one asserts the ordinary mappings still work, so the guard cannot quietly swallow a real language.

Before

The new test fails on the current code:

× returns a string for a language named after an Object member
  AssertionError: expected [Function Object] to be 'constructor'

After

✓ Prism code language options > includes Go (#7704)
✓ Prism code language options > returns a string for a language named after an Object member
✓ Prism code language options > still maps and names the languages it knows

Test Files  1 passed (1)
     Tests  3 passed (3)

The wider suite is unchanged: packages/lexical-code-prism, packages/lexical-code-shiki and packages/lexical-code-core together give 10 files, 213 tests, all passing.

`CODE_LANGUAGE_MAP` and `CODE_LANGUAGE_FRIENDLY_NAME_MAP` are plain objects,
and both lookups were plain index reads, so a language named after a member of
`Object.prototype` came back as the inherited value. `normalizeCodeLanguage`
and `getLanguageFriendlyName` are typed as returning a string and returned the
`Object` function instead.

A code block's language is whatever the document carries, so the name is not
ours to choose: the markdown transformer hands the info string of a fence
straight to `$createCodeNode`.
Copilot AI lite review requested due to automatic review settings August 8, 2026 16:57
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

@luantaraschi is attempting to deploy a commit to the Meta Open Source Team on Vercel.

A member of the Team first needs to authorize it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@etrepum
etrepum added this pull request to the merge queue Aug 9, 2026
Merged via the queue into facebook:main with commit aee0dab Aug 9, 2026
44 of 46 checks passed
@etrepum etrepum mentioned this pull request Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants