Fix remaining imc-vibe references in README and bun.lock

This commit is contained in:
Christoph Haas 2026-03-24 23:44:56 +01:00
parent ff52be8adf
commit 061126c51e
41 changed files with 613 additions and 339 deletions

View file

@ -1074,6 +1074,9 @@ function calculate_blockers(instance, analysis) {
let awaited = false;
/** @type {Array<ESTree.Statement | ESTree.VariableDeclarator>} */
let sync_group = [];
// TODO this should probably be attached to the scope?
const promises = b.id('$$promises');
@ -1088,6 +1091,13 @@ function calculate_blockers(instance, analysis) {
binding.blocker = blocker;
}
function flush_sync_group() {
if (sync_group.length === 0) return;
analysis.instance_body.async.push({ nodes: sync_group, has_await: false });
sync_group = [];
}
/**
* Analysis of blockers for functions is deferred until we know which statements are async/blockers
* @type {Array<ESTree.FunctionDeclaration | ESTree.VariableDeclarator>}
@ -1149,6 +1159,9 @@ function calculate_blockers(instance, analysis) {
trace_references(declarator, reads, writes, instance.scope);
// Needs to happen before blocker computation
if (has_await) flush_sync_group();
const blocker = /** @type {NonNullable<Binding['blocker']>} */ (
b.member(promises, b.literal(analysis.instance_body.async.length), true)
);
@ -1161,11 +1174,12 @@ function calculate_blockers(instance, analysis) {
push_declaration(id, blocker);
}
// one declarator per declaration, makes things simpler
analysis.instance_body.async.push({
node: declarator,
has_await
});
if (has_await) {
// one declarator per declaration, makes things simpler
analysis.instance_body.async.push({ nodes: [declarator], has_await: true });
} else {
sync_group.push(declarator);
}
}
}
} else if (awaited) {
@ -1177,6 +1191,9 @@ function calculate_blockers(instance, analysis) {
trace_references(node, reads, writes, instance.scope);
// Needs to happen before blocker computation
if (has_await) flush_sync_group();
const blocker = /** @type {NonNullable<Binding['blocker']>} */ (
b.member(promises, b.literal(analysis.instance_body.async.length), true)
);
@ -1187,15 +1204,20 @@ function calculate_blockers(instance, analysis) {
if (node.type === 'ClassDeclaration') {
push_declaration(node.id, blocker);
analysis.instance_body.async.push({ node, has_await });
}
if (has_await) {
analysis.instance_body.async.push({ nodes: [node], has_await: true });
} else {
analysis.instance_body.async.push({ node, has_await });
sync_group.push(node);
}
} else {
analysis.instance_body.sync.push(node);
}
}
flush_sync_group();
for (const fn of functions) {
/** @type {Set<Binding>} */
const reads_writes = new Set();

View file

@ -47,64 +47,24 @@ export function transform_body(instance_body, runner, transform) {
// Thunks for the await expressions
if (instance_body.async.length > 0) {
const thunks = instance_body.async.map((s) => {
if (s.node.type === 'VariableDeclarator') {
const visited = /** @type {ESTree.VariableDeclaration | ESTree.EmptyStatement} */ (
transform(b.var(s.node.id, s.node.init))
);
const thunks = instance_body.async.map((entry) => {
/** @type {ESTree.Statement[]} */
const entry_statements = [];
const statements =
visited.type === 'VariableDeclaration'
? visited.declarations.map((node) => {
if (
node.id.type === 'Identifier' &&
(node.id.name.startsWith('$$d') || node.id.name.startsWith('$$array'))
) {
// this is an intermediate declaration created in VariableDeclaration.js;
// subsequent statements depend on it
return b.var(node.id, node.init);
}
return b.stmt(b.assignment('=', node.id, node.init ?? b.void0));
})
: [];
if (statements.length === 1) {
const statement = /** @type {ESTree.ExpressionStatement} */ (statements[0]);
return b.thunk(statement.expression, s.has_await);
}
return b.thunk(b.block(statements), s.has_await);
for (const node of entry.nodes) {
entry_statements.push(...transform_async_node(node, transform));
}
if (s.node.type === 'ClassDeclaration') {
return b.thunk(
b.assignment(
'=',
s.node.id,
/** @type {ESTree.ClassExpression} */ ({ ...s.node, type: 'ClassExpression' })
),
s.has_await
);
if (entry_statements.length === 0) {
// Keep indices stable for async sequencing while avoiding array holes in run([...]).
return b.thunk(b.void0, false);
}
if (s.node.type === 'ExpressionStatement') {
// the expression may be a $inspect call, which will be transformed into an empty statement
const expression = /** @type {ESTree.Expression | ESTree.EmptyStatement} */ (
transform(s.node.expression)
);
if (expression.type === 'EmptyStatement') {
// Keep indices stable for async sequencing while avoiding array holes in run([...]).
return b.thunk(b.void0, false);
}
return expression.type === 'AwaitExpression'
? b.thunk(expression, true)
: b.thunk(b.unary('void', expression), s.has_await);
if (entry_statements.length === 1 && entry_statements[0].type === 'ExpressionStatement') {
return b.thunk(entry_statements[0].expression, entry.has_await);
}
return b.thunk(b.block([/** @type {ESTree.Statement} */ (transform(s.node))]), s.has_await);
return b.thunk(b.block(entry_statements), entry.has_await);
});
// TODO get the `$$promises` ID from scope
@ -113,3 +73,63 @@ export function transform_body(instance_body, runner, transform) {
return statements;
}
/**
* @param {ESTree.Statement | ESTree.VariableDeclarator} node
* @param {(node: ESTree.Node) => ESTree.Node} transform
* @returns {ESTree.Statement[]}
*/
function transform_async_node(node, transform) {
if (node.type === 'VariableDeclarator') {
const visited = /** @type {ESTree.VariableDeclaration | ESTree.EmptyStatement} */ (
transform(b.var(node.id, node.init))
);
return visited.type === 'VariableDeclaration'
? visited.declarations.map((node) => {
if (
node.id.type === 'Identifier' &&
(node.id.name.startsWith('$$d') || node.id.name.startsWith('$$array'))
) {
// This intermediate declaration is created in VariableDeclaration.js;
// subsequent statements may depend on it.
return b.var(node.id, node.init);
}
return b.stmt(b.assignment('=', node.id, node.init ?? b.void0));
})
: [];
}
if (node.type === 'ClassDeclaration') {
return [
b.stmt(
b.assignment(
'=',
node.id,
/** @type {ESTree.ClassExpression} */ ({ ...node, type: 'ClassExpression' })
)
)
];
}
if (node.type === 'ExpressionStatement') {
// The expression may be a $inspect call, which will be transformed into an empty statement.
const expression = /** @type {ESTree.Expression | ESTree.EmptyStatement} */ (
transform(node.expression)
);
if (expression.type === 'EmptyStatement') {
return [];
}
if (expression.type === 'AwaitExpression') {
return [b.stmt(expression)];
}
return [b.stmt(b.unary('void', expression))];
}
const statement = /** @type {ESTree.Statement | ESTree.EmptyStatement} */ (transform(node));
return statement.type === 'EmptyStatement' ? [] : [statement];
}

View file

@ -592,8 +592,13 @@ const svelte_visitors = (comments) => ({
},
ConstTag(node, context) {
context.write('{@');
context.visit(node.declaration);
context.write('{@const ');
const declarators = node.declaration.declarations;
for (let i = 0; i < declarators.length; i++) {
if (i > 0) context.write(', ');
context.visit(declarators[i]);
}
context.write('}');
},