Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiline Vue component props breaks import.meta.env #5387

Closed
6 tasks done
JarvisH opened this issue Mar 14, 2024 · 4 comments · Fixed by antfu/strip-literal#7
Closed
6 tasks done

Multiline Vue component props breaks import.meta.env #5387

JarvisH opened this issue Mar 14, 2024 · 4 comments · Fixed by antfu/strip-literal#7
Labels
p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@JarvisH
Copy link

JarvisH commented Mar 14, 2024

Describe the bug

When passing a component property which folds into multiple lines, any use of import.meta.env breaks the test and shows the following error:

ReferenceError: im__vite_ssr_import_meta__ is not defined

Using the following example, the error occurs when the ternary condition inside some-prop folds into multiple lines. If the text was shortened to fx. :some-prop="testValue ? 'Hello' : 'World'" the error does not occur. This also happens when passing object-syntax to class attributes etc.

The error does not occur in Vitest < 1.3.0.

<template>
  <SomeOtherComponent
    :some-prop="
      testValue
        ? 'A long value to break handling of env variables'
        : 'it needs to break into a new line'
    "
   <!-- This also breaks env variables -->
    :class="{
        'truncate text-xs': someCondition,
        'text-sm': !someOtherCondition
      }"
  >
    <div>{{ count }} x {{ times }} = {{ result }}</div>
    <button @click="times += 1">x1</button>
  </SomeOtherComponent>
</template>

<script lang="ts">
import { computed, ref, defineComponent } from 'vue';
import SomeOtherComponent from './SomeOtherComponent.vue';

export default defineComponent({
  components: {
    SomeOtherComponent,
  },
  props: {
    count: {
      type: Number,
      required: true,
    },
  },
  setup(props) {
    const times = ref(2);
    const result = computed(() => props.count * times.value);
    const testValue = ref(false);

    // any use of import.meta.env will cause an error
    console.log(import.meta.env.MODE);

    return {
      times,
      result,
      testValue,
    };
  },
});
</script>

Reproduction

https://stackblitz.com/edit/vitest-dev-vitest-tfewql?file=components%2FHello.vue

System Info

Info from Stackblitz example. It was forked from official Vitest Vue example.


System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.15.3 - /usr/local/bin/pnpm
  npmPackages:
    @vitejs/plugin-vue: latest => 5.0.4 
    vite: latest => 5.1.6 
    vitest: latest => 1.3.1

Used Package Manager

npm

Validations

@JarvisH JarvisH changed the title Multiline ternary condition passed as Vue component prop breaks import.meta.env Multiline Vue component props breaks import.meta.env Mar 15, 2024
@imjasonmiller
Copy link

I ran into the same issue (import.meta.env.DEV) and I couldn't figure out what was causing it, thank you!

@JarvisH
Copy link
Author

JarvisH commented Mar 15, 2024

I should mention I have solved this by exporting all needed env values from a separate file:

// fx utils/env.ts
export const MODE = import.meta.env.MODE
export const PROD = import.meta.env.PROD

This allows for easy mocking as well during tests.

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Mar 16, 2024

It looks like strip-literal is confused by Vue component file. v1.3.0 is where strip-literal changed from acorn to js-token https://github.com/vitest-dev/vitest/releases/tag/v1.3.0 #5136, so that may be the reason (though I'm not sure how acorn could've handle Vue either).

When I locally debug the code around here:

let s: MagicString | null = null
const cleanCode = stripLiteral(code)
const envs = cleanCode.matchAll(/\bimport\.meta\.env\b/g)

I see following transformations:

Hello.vue
  • original
<template>
  <SomeOtherComponent
    :some-prop="
      testValue
        ? 'A long value to break handling of env variables'
        : 'it needs to break into a new line'
    "
  >
    ...
  </SomeOtherComponent>
</template>

<script lang="ts">
...
    console.log(import.meta.env.MODE);
  • after stripLiteral
    • there are two additional " in :some-prop="" ... "", which is probably pushing an offset by two later in MagicString.overwrite.
<template>
  <SomeOtherComponent
    :some-prop=""
      testValue
        ? '                                               '
        : '                                 '
    ""
  >
    ...
  </SomeOtherComponent>
</template>

<script lang="  ">
...
    console.log(import.meta.env.MODE);
  • after MagicString.overwrite
<template>
  <SomeOtherComponent
    :some-prop="
      testValue
        ? 'A long value to break handling of env variables'
        : 'it needs to break into a new line'
    "
  >
    ...
  </SomeOtherComponent>
</template>

<script lang="ts">
...
    console.log(im__vite_ssr_import_meta__.envODE);

@hi-ogawa
Copy link
Contributor

This is fixed in strip-literal v2.1.0. You can upgrade the transitive dependency either by re-creating lockfile or tools such as pnpm dedupe.

I confirmed the reproduction is fixed using package.json overrides:
https://stackblitz.com/edit/vitest-dev-vitest-bifxjk?file=package.json

@github-actions github-actions bot locked and limited conversation to collaborators Apr 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants