Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions .changeset/silly-penguins-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: make `$inspect` logs come from the callsite
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/** @import { CallExpression, Expression } from 'estree' */
/** @import { CallExpression, Expression, MemberExpression } from 'estree' */
/** @import { Context } from '../types' */
import { dev, is_ignored } from '../../../../state.js';
import * as b from '#compiler/builders';
import { get_rune } from '../../../scope.js';
import { transform_inspect_rune } from '../../utils.js';
import { should_proxy } from '../utils.js';

/**
Expand Down Expand Up @@ -73,7 +72,7 @@ export function CallExpression(node, context) {

case '$inspect':
case '$inspect().with':
return transform_inspect_rune(node, context);
return transform_inspect_rune(rune, node, context);
}

if (
Expand Down Expand Up @@ -104,3 +103,32 @@ export function CallExpression(node, context) {

context.next();
}

/**
* @param {'$inspect' | '$inspect().with'} rune
* @param {CallExpression} node
* @param {Context} context
*/
function transform_inspect_rune(rune, node, context) {
if (!dev) return b.empty;

const { visit } = context;

const call =
rune === '$inspect'
? node
: /** @type {CallExpression} */ (/** @type {MemberExpression} */ (node.callee).object);

const args = call.arguments.map((arg) => /** @type {Expression} */ (context.visit(arg)));

const inspector =
rune === '$inspect'
? 'console.log'
: /** @type {Expression} */ (context.visit(node.arguments[0]));

// by passing an arrow function, the log appears to come from the `$inspect` callsite
// rather than the `inspect.js` file containing the utility
const fn = b.arrow([b.rest(b.id('$$args'))], b.call(inspector, b.spread(b.id('$$args'))));

return b.call('$.inspect', b.thunk(b.array(args)), fn);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/** @import { CallExpression, Expression } from 'estree' */
/** @import { CallExpression, Expression, MemberExpression } from 'estree' */
/** @import { Context } from '../types.js' */
import { is_ignored } from '../../../../state.js';
import { dev, is_ignored } from '../../../../state.js';
import * as b from '#compiler/builders';
import { get_rune } from '../../../scope.js';
import { transform_inspect_rune } from '../../utils.js';

/**
* @param {CallExpression} node
Expand Down Expand Up @@ -51,7 +50,23 @@ export function CallExpression(node, context) {
}

if (rune === '$inspect' || rune === '$inspect().with') {
return transform_inspect_rune(node, context);
if (!dev) return b.empty;

const call =
rune === '$inspect'
? node
: /** @type {CallExpression} */ (/** @type {MemberExpression} */ (node.callee).object);

const args = call.arguments.map((arg) => /** @type {Expression} */ (context.visit(arg)));

const inspector =
rune === '$inspect'
? 'console.log'
: /** @type {Expression} */ (context.visit(node.arguments[0]));

// TODO is the `init` doing any work on the server? should it be `$inspect` instead?
// should we include a stack trace?
return b.call(inspector, b.literal('init'), ...args);
}

context.next();
Expand Down
29 changes: 0 additions & 29 deletions packages/svelte/src/compiler/phases/3-transform/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,32 +450,3 @@ export function determine_namespace_for_children(node, namespace) {

return node.metadata.mathml ? 'mathml' : 'html';
}

/**
* @template {TransformState} T
* @param {CallExpression} node
* @param {Context<any, T>} context
*/
export function transform_inspect_rune(node, context) {
const { state, visit } = context;
const as_fn = state.options.generate === 'client';

if (!dev) return b.empty;

if (node.callee.type === 'MemberExpression') {
const raw_inspect_args = /** @type {CallExpression} */ (node.callee.object).arguments;
const inspect_args =
/** @type {Array<Expression>} */
(raw_inspect_args.map((arg) => visit(arg)));
const with_arg = /** @type {Expression} */ (visit(node.arguments[0]));

return b.call(
'$.inspect',
as_fn ? b.thunk(b.array(inspect_args)) : b.array(inspect_args),
with_arg
);
} else {
const arg = node.arguments.map((arg) => /** @type {Expression} */ (visit(arg)));
return b.call('$.inspect', as_fn ? b.thunk(b.array(arg)) : b.array(arg));
}
}
5 changes: 2 additions & 3 deletions packages/svelte/src/internal/client/dev/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { untrack } from '../runtime.js';

/**
* @param {() => any[]} get_value
* @param {Function} [inspector]
* @param {Function} inspector
*/
// eslint-disable-next-line no-console
export function inspect(get_value, inspector = console.log) {
export function inspect(get_value, inspector) {
validate_effect('$inspect');

let initial = true;
Expand Down
9 changes: 0 additions & 9 deletions packages/svelte/src/internal/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,6 @@ export function ensure_array_like(array_like_or_iterator) {
return [];
}

/**
* @param {any[]} args
* @param {Function} [inspect]
*/
// eslint-disable-next-line no-console
export function inspect(args, inspect = console.log) {
inspect('init', ...args);
}

/**
* @template V
* @param {() => V} get_value
Expand Down
Loading