Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions dev/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,32 @@ function compiler(options) {

index = -1

// The handler this-binding receives the same fields as `context` plus a
// per-event `sliceSerialize`. Build the merged object as a stable-shape
// literal so V8 keeps a single hidden class for it and can inline the
// construction; the previous Object.assign({sliceSerialize: ...}, context)
// form created the same object but went through a copy-loop and gave V8
// less to optimize. A fresh object per event preserves the previous
// contract that handlers may capture `this` or reassign top-level fields
// without leaking into subsequent events.
Comment on lines +255 to +257
while (++index < events.length) {
const handler = config[events[index][0]]

if (own.call(handler, events[index][1].type)) {
handler[events[index][1].type].call(
Object.assign(
{sliceSerialize: events[index][2].sliceSerialize},
context
),
events[index][1]
const event = events[index]
const handler = config[event[0]]

if (own.call(handler, event[1].type)) {
handler[event[1].type].call(
{
sliceSerialize: event[2].sliceSerialize,
stack: context.stack,
tokenStack: context.tokenStack,
config: context.config,
enter: context.enter,
exit: context.exit,
buffer: context.buffer,
resume: context.resume,
data: context.data
},
event[1]
)
}
}
Expand Down
9 changes: 9 additions & 0 deletions dev/lib/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import type {ParseOptions, Token} from 'micromark-util-types'

/**
* Compiler context.
*
* The object passed to handlers as `this` is scoped to a single handler
* call. A fresh object is constructed for every event in the dispatch loop,
* so handlers must not retain a `this` reference between events nor reassign
* its top-level fields and expect the change to leak into subsequent events.
* Cross-event state belongs in `this.data`, which is the shared key/value
* store described below; mutations through `this.stack`, `this.tokenStack`,
* and the `enter`/`exit`/`buffer`/`resume` helpers go to the same shared
* underlying objects and remain visible across events as before.
*/
export interface CompileContext {
/**
Expand Down
Loading