biome nursery/useVueBaseImport
labelled safe
Analysis Nemotron 3 Super
The rule flags imports from internal Vue subpackages like @vue/reactivity or @vue/runtime-dom, recommending they be replaced with imports from the main 'vue' package.
Fix: The autofix replaces the import source from the internal Vue package (e.g., '@vue/reactivity') to the main 'vue' package while preserving the imported bindings (names, namespace, or star). For example, 'import { ref } from "@vue/reactivity"' becomes 'import { ref } from "vue"'.
12 hazards
- Named imports: If the imported name (e.g., 'ref') is not actually exported from the main 'vue' package, the rewrite causes a runtime error due to missing export.
- Namespace imports: Rewriting 'import * as VueReactivity from "@vue/reactivity"' to 'import * as VueReactivity from "vue"' may include unintended exports from 'vue', potentially causing naming conflicts or exposing internal APIs.
- Star exports: Rewriting 'export * from "@vue/runtime-dom"' to 'export * from "vue"' may re-export unintended bindings from 'vue', altering the module's public interface.
- Side-effect imports: If the internal package has side effects (e.g., patches global state) not present in the main 'vue' package, removing the import drops those side effects.
- Type-only imports: In TypeScript, 'import type { Ref } from "@vue/reactivity"' rewritten to 'import type { Ref } from "vue"' may fail if 'Ref' is not available as a type in the main package's type exports.
- Conditional/external mapping: If the project uses module aliases or conditional exports (e.g., via package.json 'exports' field) that map 'vue' to a different build than the internal packages, the rewrite may resolve to an unintended module version.
- Internal-only flag usage: The rule allows certain internal-only imports (e.g., dev-only flags); rewriting those would violate the rule's intent and possibly break builds targeting production.
- Comment attachment: If comments are attached to the import line (e.g., // TODO: migrate), the autofix may discard them during replacement, losing developer intent.
- Evaluation order: If multiple imports from the same internal package exist across files, deduplication via the rewrite may change load order if side effects were relied upon.
- Path resolution: In environments with custom module resolution (e.g., webpack aliases), replacing '@vue/reactivity' with 'vue' may bypass intended redirects or fallbacks.
- Build-time transforms: If the internal package is processed by a transform (e.g., treeshading) that assumes its presence, removing it may prevent dead code elimination or cause bundle bloat.
- Version skew: If the project uses different versions of 'vue' and its internal packages (unsupported but possible), the rewrite may import from a mismatched version, causing API mismatches.
Findings
| program | oracle | label | judge | status | summary |
|---|---|---|---|---|---|
| r1-p001 | fix-changes-behavior | labelled safe | program-bug · low | related | The program fails both before and after the fix because neither '@vue/reactivity' nor 'vue' packages are installed in the execution environment. The observed d… |
| r1-p003 | fix-changes-behavior | labelled safe | program-bug · low | duplicate | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The … |
| r1-p004 | fix-changes-behavior | labelled safe | program-bug · low | related | The program fails both before and after the fix because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The rewrite correctly ch… |
| r1-p008 | fix-changes-behavior | labelled safe | program-bug · low | related | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The … |
| r2-p001 | fix-changes-behavior | labelled safe | program-bug · low | related | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The … |
| r2-p002 | fix-changes-behavior | labelled safe | program-bug · low | related | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/runtime-core' nor 'vue' is installed in the execution environment. Th… |
| r2-p004 | fix-changes-behavior | labelled safe | program-bug · low | related | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The … |
| r2-p005 | fix-changes-behavior | labelled safe | program-bug · low | duplicate | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/shared' nor 'vue' is installed in the execution environment. The orac… |
| r2-p008 | fix-changes-behavior | labelled safe | program-bug · low | related | Both the original and fixed programs fail with ERR_MODULE_NOT_FOUND because neither '@vue/reactivity' nor 'vue' is installed in the execution environment. The … |
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fix-changes-behavior | Path Resolution Hazard | In environments with custom module resolution (e.g., webpack aliases), replacing '@vue/reactivity' with 'vue' may bypass intended redirects or fallbacks. |
| r1-p003 | fix-changes-behavior | Conditional/External Mapping Hazard | If the project uses module aliases or conditional exports (e.g., via package.json 'exports' field) that map 'vue' to a different build than the internal packages, the rewrite may resolve to an uninten |
| r1-p004 | fix-changes-behavior | Comment Attachment Hazard | If comments are attached to the import line (e.g., // TODO: migrate), the autofix may discard them during replacement, losing developer intent. |
| r1-p005 | invalid | Namespace Imports Hazard | Rewriting 'import * as VueReactivity from "@vue/reactivity"' to 'import * as VueReactivity from "vue"' may include unintended exports from 'vue', potentially causing naming conflicts or exposing inter |
| r1-p006 | silent prediction off | Regular Expressions Hazard | regular expressions: escapes, unicode flag, lastIndex with the g flag |
| r1-p007 | invalid | Type-only Imports Hazard | In TypeScript, 'import type { Ref } from "@vue/reactivity"' rewritten to 'import type { Ref } from "vue"' may fail if 'Ref' is not available as a type in the main package's type exports. |
| r1-p008 | fix-changes-behavior | Numeric/String Coercion Hazard | numeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt |
| r2-p001 | fix-changes-behavior | Comments attached to removed or moved code | comments attached to the removed or moved code |
| r2-p002 | fix-changes-behavior | Strict vs sloppy mode semantics | strict vs sloppy mode semantics |
| r2-p003 | silent | Internal-only flag usage | Internal-only flag usage: The rule allows certain internal-only imports (e.g., dev-only flags); rewriting those would violate the rule's intent and possibly break builds targeting production. |
| r2-p004 | fix-changes-behavior | Async/await ordering, generators and yield position | async/await ordering, generators and yield position |
| r2-p005 | fix-changes-behavior | Getters, setters and Object.defineProperty side effects | getters, setters and Object.defineProperty side effects |
| r2-p006 | invalid | Name collisions across scopes after a move (shadowing) | name collisions across scopes after a move (shadowing) |
| r2-p007 | invalid | Type-only imports: In TypeScript, 'import type { Ref } from "@vue/reactivity"' rewritten to 'import type { Ref } from "v | Type-only imports: In TypeScript, 'import type { Ref } from "@vue/reactivity"' rewritten to 'import type { Ref } from "vue"' may fail if 'Ref' is not available as a type in the main package's type exp |
| r2-p008 | fix-changes-behavior | Sparse arrays, holes, Array(n) vs [n], array-likes | sparse arrays, holes, Array(n) vs [n], array-likes |
Sources
r1-p001 · Path Resolution Hazard
1// Simulate webpack alias: @vue/reactivity -> ./local-reactivity
2const originalRequire = require;
3function require(id) {
4 if (id === '@vue/reactivity') return { ref: () => ({ value: 'patched' }) };
5 return originalRequire(id);
6}
7// --- Rule target ---
8import { ref } from '@vue/reactivity'; // expect_trigger=true
9// --------------------
10console.log(ref().value);
--- orig.js 2026-10-17 16:52:38.881042082 -0400 +++ fixed.js 2026-10-17 16:52:39.190047354 -0400 @@ -5,6 +5,6 @@ return originalRequire(id); } // --- Rule target --- -import { ref } from '@vue/reactivity'; // expect_trigger=true +import { ref } from 'vue'; // expect_trigger=true // -------------------- console.log(ref().value);
r1-p003 · Conditional/External Mapping Hazard
1// Simulate conditional exports: 'vue' -> esm, '@vue/*' -> cjs
2const modules = {
3 vue: { ref: () => ({ value: 'esm-ref' }) },
4 '@vue/reactivity': { ref: () => ({ value: 'cjs-ref' }) }
5};
6function require(id) { return modules[id]; }
7// --- Rule target ---
8import { ref } from '@vue/reactivity'; // expect_trigger=true
9// --------------------
10console.log(ref().value);
--- orig.js 2026-10-17 16:52:39.360050253 -0400 +++ fixed.js 2026-10-17 16:52:39.641055046 -0400 @@ -5,6 +5,6 @@ }; function require(id) { return modules[id]; } // --- Rule target --- -import { ref } from '@vue/reactivity'; // expect_trigger=true +import { ref } from 'vue'; // expect_trigger=true // -------------------- console.log(ref().value);
r1-p004 · Comment Attachment Hazard
1// TODO: migrate to main vue when ready
2// --- Rule target ---
3import { ref } from '@vue/reactivity'; // keep this comment
4// --------------------
5const r = ref();
6r.value = 42;
7console.log(r.value);
--- orig.js 2026-10-17 16:52:39.817058047 -0400 +++ fixed.js 2026-10-17 16:52:40.083062582 -0400 @@ -1,6 +1,6 @@ // TODO: migrate to main vue when ready // --- Rule target --- -import { ref } from '@vue/reactivity'; // keep this comment +import { ref } from 'vue'; // keep this comment // -------------------- const r = ref(); r.value = 42;
r1-p005 · Namespace Imports Hazard (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-51-5)
1// Internal Vue reactivity only exposes ref, reactive
2// Main vue also exposes defineComponent (which we don't want here)
3let VueReactivity;
4// --- Rule target ---
5import * as VueReactivity from '@vue/reactivity'; // expect_trigger=true
6// --------------------
7if ('defineComponent' in VueReactivity) {
8 console.log('ERROR: defineComponent leaked into reactivity namespace');
9} else {
10 console.log('OK: only reactivity exports present');
11}
r1-p006 · Regular Expressions Hazard
1// Internal Vue shared exports a regex utility used for template parsing
2let TemplateRegex;
3// --- Rule target ---
4import { compileTemplate } from '@vue/shared'; // expect_trigger=true
5// --------------------
6TemplateRegex = /<\s*([a-zA-Z]+)/gu;
7TemplateRegex.lastIndex = 0;
8const match = TemplateRegex.exec('<div>hello</div>');
9console.log(match ? match[1] : null);
r1-p007 · Type-only Imports Hazard (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-51-5)
1// Simulate TS type-only import behavior at runtime via structural check
2let RefType;
3// --- Rule target ---
4import type { Ref } from '@vue/reactivity'; // expect_trigger=true (simulated)
5// --------------------
6// In real TS, this would be erased; here we simulate by checking if Ref is a type-like object
7// We assume @vue/reactivity exports Ref as a type, but main 'vue' does not in this scenario
8if (typeof Ref === 'undefined') {
9 console.log('Ref type not available in main vue - simulation of TS error');
10} else {
11 console.log('Ref type available');
12}
r1-p008 · Numeric/String Coercion Hazard
1// Internal Vue reactivity returns objects with custom valueOf used in reactive calculations
2let reactiveValue;
3// --- Rule target ---
4import { reactive } from '@vue/reactivity'; // expect_trigger=true
5// --------------------
6reactiveValue = reactive({ value: 5 });
7// Object with custom valueOf that returns a BigInt
8const obj = { valueOf: () => 3n };
9console.log(String(reactiveValue.value + obj)); // Should be '8' if reactive unwraps correctly
10console.log(`${reactiveValue.value}${obj}`); // Template literal: relies on String() coercion
--- orig.js 2026-10-17 16:52:40.569070864 -0400 +++ fixed.js 2026-10-17 16:52:40.833075362 -0400 @@ -1,7 +1,7 @@ // Internal Vue reactivity returns objects with custom valueOf used in reactive calculations let reactiveValue; // --- Rule target --- -import { reactive } from '@vue/reactivity'; // expect_trigger=true +import { reactive } from 'vue'; // expect_trigger=true // -------------------- reactiveValue = reactive({ value: 5 }); // Object with custom valueOf that returns a BigInt
r2-p001 · Comments attached to removed or moved code
1// This comment should stay
2import { ref } /* inline */ from "@vue/reactivity"; // trailing
3console.log(typeof ref === "function" ? "ok" : "missing");
--- orig.js 2026-10-17 16:52:51.990264505 -0400 +++ fixed.js 2026-10-17 16:52:52.336270340 -0400 @@ -1,3 +1,3 @@ // This comment should stay -import { ref } /* inline */ from "@vue/reactivity"; // trailing +import { ref } /* inline */ from "vue"; // trailing console.log(typeof ref === "function" ? "ok" : "missing");
r2-p002 · Strict vs sloppy mode semantics
1"use strict";
2import { reactive } from "@vue/runtime-core";
3try {
4 reactive(null);
5} catch (e) {
6 console.log(e.constructor.name);
7}
--- orig.js 2026-10-17 16:52:52.511273291 -0400 +++ fixed.js 2026-10-17 16:52:52.793278046 -0400 @@ -1,5 +1,5 @@ "use strict"; -import { reactive } from "@vue/runtime-core"; +import { reactive } from "vue"; try { reactive(null); } catch (e) {
r2-p003 · Internal-only flag usage
1console.log("Skipping internal-only import as rule should not fire");
Skipping internal-only import as rule should not fire
r2-p004 · Async/await ordering, generators and yield position
1import { watch } from "@vue/reactivity";
2async function test() {
3 await Promise.resolve();
4 return watch(() => 1, () => {});
5}
6test().then(r => console.log(typeof r === "function" ? "stop" : "bad"));
--- orig.js 2026-10-17 16:52:53.189284721 -0400 +++ fixed.js 2026-10-17 16:52:53.444289018 -0400 @@ -1,4 +1,4 @@ -import { watch } from "@vue/reactivity"; +import { watch } from "vue"; async function test() { await Promise.resolve(); return watch(() => 1, () => {});
r2-p005 · Getters, setters and Object.defineProperty side effects
1import { isRef } from "@vue/shared";
2const obj = {};
3Object.defineProperty(obj, "value", {
4 get: () => isRef({}) ? 1 : 0
5});
6console.log(obj.value);
--- orig.js 2026-10-17 16:52:53.613291865 -0400 +++ fixed.js 2026-10-17 16:52:53.891296549 -0400 @@ -1,4 +1,4 @@ -import { isRef } from "@vue/shared"; +import { isRef } from "vue"; const obj = {}; Object.defineProperty(obj, "value", { get: () => isRef({}) ? 1 : 0
r2-p006 · Name collisions across scopes after a move (shadowing) (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-51-5)
1let nextTick = "outer";
2{
3 import { nextTick } from "@vue/runtime-dom";
4 console.log(nextTick === "outer" ? "shadowed" : typeof nextTick);
5}
r2-p007 · Type-only imports: In TypeScript, 'import type { Ref } from "@vue/reactivity"' rewritten to 'import type { Ref } from "v (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-51-5)
1// @ts-ignore
2import type { Ref } from "@vue/reactivity";
3/** @type {any} */ let x;
4console.log("type-only import parsed");
r2-p008 · Sparse arrays, holes, Array(n) vs [n], array-likes
1import { ref } from "@vue/reactivity";
2const arr = new Array(3);
3arr[0] = ref(0);
4arr[2] = ref(2);
5console.log(arr.map((v, i) => v ? `has${i}` : `hole`));
--- orig.js 2026-10-17 16:52:54.142300776 -0400 +++ fixed.js 2026-10-17 16:52:54.424305524 -0400 @@ -1,4 +1,4 @@ -import { ref } from "@vue/reactivity"; +import { ref } from "vue"; const arr = new Array(3); arr[0] = ref(0); arr[2] = ref(2);