Skip to content

Lexer.lookahead() seems to violate its comment about not modifying the state of the lexer #2764

Closed
@haikusw

Description

@haikusw

Apologies in advance if I'm misreading this and for not providing a PR that includes a fix and a test verifying the issue (no Typescript setup or experience).

I'm working on enhancing the Swift graphql project which mirrors this js implementation with more complete support for some of the graphql definition language parsing it is currently missing.

In reading the source for the lexer.js lookahead function I see the comment says:

/**
   * Looks ahead and returns the next non-ignored token, but does not change
   * the state of Lexer.
   */

However it appears that blockstring support modified the implementation of readToken called by lookahead such that it can now change the state of the lexer in violation of the claim in the comment above and the usual expectation for a lookahead style function of a lexer. Not sure if that actually matters in this codebase (yet ;) ), but…

This modification of the lexer is possible because lookahead calls readToken passing in the lexer and readToken calls readBlockString which also passes along the lexer - on line 192.

The passed-in lexer is modified in readBlockString on line 569 and again down further on lines 569, 570 and 578.

Thought I'd mention it so that someone working on the project can write a quick test and decide if this is the bug lurking in the shadows it appears to potentially be.

Cheers.

P.S. In my implementation of lookahead I simply save off line and lineStart at the beginning and then restore before returning from lookahead. Somewhat fragile in that any future changes to readToken or readBlockString that modify additional fields of the lexer may not know to update the save/restore code in lookahead, so a collection of unit tests to catch this if it happens is something I plan to add. Considered duplicating the lexer but that has performance considerations. Anyway, seems likely something similar will work in this js version.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions