Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: template abbreviation of end tag #166

Open
CathLee opened this issue Mar 25, 2024 · 3 comments
Open

perf: template abbreviation of end tag #166

CathLee opened this issue Mar 25, 2024 · 3 comments

Comments

@CathLee
Copy link

CathLee commented Mar 25, 2024

related #112
I've been working on optimizing the abbreviation of end tags in templates and would greatly appreciate it if you could review my solution at your convenience.So there is my solution:

Take the HTML code <div><span></span></div> as an example. The parsing mechanism sequentially executes handling (<div, <span) and closing (</) actions. My optimization's primary objective is to leverage self-closing tags whenever feasible, especially for the sequence's terminal element.

My strategy unfolds in two steps:

  1. Determine whether a close action directly follows a handle action, identified by this.currentStage === 'stateInTagName'. When this condition is met, we flag the current Node with isShouldSelfClosing. This flag is later used during the transformElement phase to implement the optimization. If the condition isn't met, we don't set the flag.
  2. Modify the currentStage attribute to accurately represent the ongoing parsing phase, thus accommodating various tag processing scenarios.

here is some draft code

// packages/compiler-core/src/tokenizer.ts
private stateInClosingTagName(c: number): void {
    if (c === CharCodes.Gt || isWhitespace(c)) {
      this.cbs.onclosetag(this.sectionStart, this.index)
      this.cbs.onclosetag(
        this.sectionStart,
        this.index,
        this.currentStage === 'stateInTagName',// `close` operation after `handle` operation
      )
      this.sectionStart = -1

      this.state = State.AfterClosingTagName
      this.stateAfterClosingTagName(c)
    }
    this.currentStage === 'stateInClosingTagName' //change currentStage in different flow
  }
// packages/compiler-core/src/parser.ts
onclosetag(start, end, isLastElement) {
    const name = getSlice(start, end)
    if (!currentOptions.isVoidTag(name)) {
      let found = false
      for (let i = 0; i < stack.length; i++) {
        const e = stack[i]
        if (e.tag.toLowerCase() === name.toLowerCase()) {
          found = true
           // if is the isLastElement make a tag with `isShouldSelfClosing`
          if (isLastElement) {
            e.isShouldSelfClosing = true
          }
          if (i > 0) {
            emitError(ErrorCodes.X_MISSING_END_TAG, stack[0].loc.start.offset)
          }
          for (let j = 0; j <= i; j++) {
            const el = stack.shift()!
            onCloseTag(el, end, j < i)
          }
          break
        }
      }
      if (!found) {
        emitError(ErrorCodes.X_INVALID_END_TAG, backTrack(start, CharCodes.Lt))
      }
    }
  },
// packages/compiler-vapor/src/transforms/transformElement.ts 
const { node } = context
  if (node.isShouldSelfClosing) {
    context.template += context.childrenTemplate.join('')
  } else {
    context.template += `>` + context.childrenTemplate.join('')
  }
  context.template += `>` + context.childrenTemplate.join('')
  // TODO remove unnecessary close tag, e.g. if it's the last element of the template
  if (!isVoidTag(tag)) {
    const { node } = context
    if (node.isShouldSelfClosing) {
      context.template += ` />`
    } else {
      context.template += `</${tag}>`
    }
  }

I've integrated the isShouldSelfClosing flag into the standard Node structure and have made the necessary updates in tokenizer.ts. However, I'm uncertain if this is the best approach.

Any feedback or advice you could offer on this strategy would be incredibly valuable to me~~
ps:code is in https://github.com/CathLee/core-vapor/tree/transform/close_tag

@sxzz sxzz mentioned this issue Apr 17, 2024
7 tasks
@sxzz
Copy link
Member

sxzz commented Apr 17, 2024

Could you please create a PR for your code, so that we can discuss some details conveniently?

@sxzz
Copy link
Member

sxzz commented Apr 18, 2024

I added some unit tests for your reference.
https://github.com/vuejs/core-vapor/blob/a68445bdac84b4c49ca926378bfe77f8a9e73fbd/packages/compiler-vapor/__tests__/abbreviation.spec.ts

@CathLee
Copy link
Author

CathLee commented Apr 21, 2024

I added some unit tests for your reference. https://github.com/vuejs/core-vapor/blob/a68445bdac84b4c49ca926378bfe77f8a9e73fbd/packages/compiler-vapor/__tests__/abbreviation.spec.ts
sure!!🤓,i will try my best to do it right now🏎

@sxzz sxzz changed the title perf:template abbreviation of end tag perf: template abbreviation of end tag May 5, 2024
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

No branches or pull requests

2 participants