enhance: bump to Takumi 0.70#491
Merged
harlan-zw merged 3 commits intonuxt-modules:mainfrom Mar 2, 2026
Merged
Conversation
Collaborator
|
Ignore the ecosystem tests trying to get them running still |
Contributor
Author
|
kane50613/takumi@36fba31 eliminates the need to rewrite svgs |
Collaborator
|
Test timeouts are on main so i'll merge this for now and get that fixed. |
Collaborator
|
This seems to reproduce the issue immediately /**
* Reproduces "double free or corruption (fasttop)" crash in @takumi-rs/core.
*
* The native Renderer is not safe for concurrent loadFont + render calls on
* the same instance. This simulates what happens when a Nuxt server handles
* multiple OG image requests concurrently — each request loads fonts and
* renders on the shared Renderer instance.
*
* Usage: node test/repro-double-free.mjs
*/
import { readFileSync } from 'node:fs'
import { Renderer } from '@takumi-rs/core'
const CONCURRENCY = 50
const ROUNDS = 20
const fontPath = 'test/fixtures/app-dir/.output/public/_og-static-fonts/inter-400-latin.ttf'
const fontData = new Uint8Array(readFileSync(fontPath))
const nodes = {
type: 'container',
tw: 'flex w-full h-full bg-slate-900 items-center justify-center',
children: [
{ type: 'text', text: 'Hello World', tw: 'text-white text-5xl' },
{
type: 'container',
tw: 'flex flex-col gap-2 p-4',
children: Array.from({ length: 10 }, (_, i) => ({
type: 'text',
text: `Item ${i} — ${'x'.repeat(50)}`,
tw: 'text-gray-300 text-lg',
})),
},
],
}
const opts = { width: 1200, height: 630, format: 'png' }
// Simulate concurrent requests: each "request" creates/reuses a renderer,
// loads a font subset, and renders — exactly like the Nuxt server does.
const renderer = new Renderer()
async function simulateRequest(id) {
// Each request loads a "new" font subset (unique name) then renders
await renderer.loadFont({
name: `inter-subset-${id}`,
data: fontData,
weight: 400,
style: 'normal',
})
return renderer.render(nodes, opts)
}
for (let round = 1; round <= ROUNDS; round++) {
console.log(`Round ${round}/${ROUNDS}: ${CONCURRENCY} concurrent loadFont+render...`)
await Promise.all(Array.from({ length: CONCURRENCY }, (_, i) =>
simulateRequest(round * CONCURRENCY + i),
))
}
console.log(`Completed ${ROUNDS * CONCURRENCY} renders without crash.`) |
Contributor
Author
|
Thanks for catching this! I thought napi-rs would have guardrails around accessing to prevent race-conditions like this 😅 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Linked issue
❓ Type of change
📚 Description
Trying to address the memory issue mentioned in npmx-dev/npmx.dev#1770 npmx-dev/npmx.dev#1654 by getting rid of
asUint8Arraycompletely and hope it resolves the issue.