Skip to content

Fix parsing method member forms#34

Closed
davejcameron wants to merge 1 commit into
dy:mainfrom
davejcameron:dc.parse-method-members
Closed

Fix parsing method member forms#34
davejcameron wants to merge 1 commit into
dy:mainfrom
davejcameron:dc.parse-method-members

Conversation

@davejcameron
Copy link
Copy Markdown
Contributor

Problem

Jessie already parses object method shorthand and static class members, but two valid JavaScript method forms fall through to misleading parser errors.

({ "x/y.js"(exports, module) { module.exports = {} } })
class A { static m(a) { return a } }

Both should parse, but currently report Unclosed { around the method body.

Fix

Allow the method shorthand parser to accept static string-literal property keys, preserving the existing [':', key, ['=>', ...]] AST shape.

Parse static m() {} class members as ['static', [':', 'm', ['=>', ...]]], matching the existing static member wrapper and method shorthand representation.

Validation

  • Direct parser tests for string-literal object methods and static class methods
  • node test/feature/async-class.js: 23 tests, 64 assertions

I also ran pnpm test; it gets through the bundle/perf tests but still has the existing unicode scaling stack overflows unrelated to this change.

Comment thread feature/class.js

// static member → ['static', member]
unary('static', PREFIX);
token('static', PREFIX, a => {
Copy link
Copy Markdown
Owner

@dy dy May 13, 2026

Choose a reason for hiding this comment

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

Can it be kept as unary call - we tend to keep token for low-level primitives outside of normal syntax rules.
@copilot

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates Jessie’s parser to correctly handle two previously-misparsed JavaScript method forms: object literal method shorthand with string-literal keys and static class methods, aligning them with the existing method-shorthand / static-member AST conventions.

Changes:

  • Extend object method-shorthand parsing to accept string-literal property keys (e.g. { "x/y.js"() {} }).
  • Extend static parsing to recognize static m() {} as a static class method node shape.
  • Add direct parser tests covering both new cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
test/feature/async-class.js Adds parser tests for static class methods and string-literal object method shorthand.
feature/class.js Reworks static parsing to recognize static name(params) { body } as a static method node.
feature/accessor.js Updates method-shorthand parsing to accept static property keys, including string literals.
Comments suppressed due to low confidence (1)

feature/accessor.js:55

  • Unwrapping a string-literal key node ([, "..."]) into a plain string changes the key representation from a literal node to an identifier-like string. For non-identifier keys like "x/y.js", this will make downstream codegen/bundling (which prints string keys verbatim) emit invalid JS (x/y.js: ...). Prefer keeping the key as the original literal node (or otherwise marking it as a quoted key) so stringify/codegen can safely quote or emit a computed key.
  // Only handle infix position with a static property key in low-precedence context (object literal)
  if (!a) return;
  if (Array.isArray(a) && a[0] === undefined) a = a[1];
  if (typeof a !== 'string') return;
  const params = expr(0, CPAREN) || null;
  space();
  // Not followed by { - not method shorthand, fall through
  if (cur.charCodeAt(idx) !== OBRACE) return;
  skip();
  return [':', a, ['=>', ['()', params], expr(0, CBRACE) || null]];

Comment thread feature/class.js
Comment on lines +10 to +18
token('static', PREFIX, a => {
if (a) return;
space();
const name = next(parse.id);
if (!name) return;
space();
if (cur.charCodeAt(idx) !== OPAREN) return ['static', name];
skip();
const params = expr(0, CPAREN) || null;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback
I would try using unary still for static - token is for low-level primitives

@dy
Copy link
Copy Markdown
Owner

dy commented May 13, 2026

Thanks @davejcameron — landed an alternative implementation in 3dec13d that keeps unary('static', ...) and routes static m() {} and string-literal-key methods through the existing method-shorthand handler in accessor.js.

Two reasons for the alternative:

  1. token('static', ...) re-implemented method-shorthand parsing inline and broke static #x (private fields), since next(parse.id) won't consume #. The merged change preserves unary('static') (raised above ACCESS precedence so static m collapses to ['static', 'm'] and the outer ( reaches the method-shorthand handler).
  2. The string-literal key is kept as a literal node [, "x/y.js"] (matching how { "y": 2 } is represented in test/parse.js:266) rather than unwrapped to a plain string — avoids the codegen issue Copilot flagged.

@dy dy closed this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants