Skip to content

insertBefore()/insert() accept prototype-inherited keys (e.g. "toString") and then silently insert nothingΒ #4174

Open

Description

@rahul05ranjan

While playing with the grammar utilities on master (v2 alpha), I noticed the anchor-key guard in insert() uses the in operator:

src/util/insert.js:57

if (!(atKey in grammar)) {
    throw new Error(`"${atKey}" has to be a key of grammar.`);
}
``"

Because `in` walks the prototype chain, any key inherited from `Object.prototype` β€” `toString`, `constructor`, `hasOwnProperty`, `__proto__`, ... β€” passes the check even though it is not a key of the grammar at all. After that, `key === atKey` never matches while re-inserting the grammar's own keys, so `betterAssign(grammar, insert)` is never called: **no error is thrown and the new tokens are silently dropped**.

Minimal repro against the current `src/util/insert.js` (run with node, the package is ESM):

```js
import { insertBefore } from './prism/src/util/insert.js';

const grammar = {
    comment: { pattern: /x/, greedy: true },
    string:  { pattern: /y/ },
};

// "toString" is not a key of the grammar β€” this should throw
insertBefore(grammar, 'toString', { 'new-token': { pattern: /z/ } });

console.log(JSON.stringify(Object.keys(grammar)));
// -> ["comment","string"]   (expected: TypeError "toString has to be a key of grammar.")

Same outcome for insertAfter(grammar, 'constructor', {...}) and insert(grammar, 'hasOwnProperty', {...}). As a control, a genuinely missing key like a typo ("strng") does throw correctly, and a valid own key works as intended β€” it is only the Object.prototype names that slip through the guard and turn into a silent no-op.

Since the whole point of this guard is to catch a wrong anchor key with a loud error, I'd expect it to check own properties only, e.g.:

if (!Object.hasOwn(grammar, atKey)) { ... }

For context, this bit me while wiring up a small grammar-patching utility where the anchor key came from user input; the call "succeeded" and nothing showed up in the output, which took a while to track down. Apologies if this is known/duplicate β€” I searched the tracker for insertBefore reports and found nothing matching.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions