Subscribe on changes!

Use "@vue/compiler-sfc" to get a root component, but the _ctx of render function doesn't have any my variable and throw a reading undefined error.

avatar
Aug 13th 2023

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNp1Vttu2zgQ/RVCWMB2oUib7S6wcJOgNwNtgV6QpH2JAkGR6ESJTAokpTpI/e89w4ts2U1eIg7ncmbmzNBP0Zu2TfqOR/PoRJeqbs1ZJjJRr1qpDHti/WdZ8eaSrw0rNMu3x5iViheGLxq+4sL8+IILq3IojtnP2ty9rxUvTd1zbdXGopjJlou3jSwf7O1w2guz1fiDeMOWSq5YFiGfLHq1k0XFl7Xg7yTOAurWwb7seWtEsigPVUoptGF5Xg5eTg8cT58ywZjmpmuned4q2SJbK2OMr1up+Rwe3BdJN7NwG6TTGUKRwIVbSrVCnIDK+ae/vmg6OJtooyZOthlb5rkCDCV4lefwMBiSR2/g9b/e3KMziUvlGzBzZR4Bf2sfs0me1/rCcuaCspsMaSEx0a24Km4a4FkWjebxHkijUMIxRud7BNLebDJhddIXdEpT1P81GpBS0euGqyO9LFnPla6lyCJWayi8TF4m/2ZREizwb2int3PIwS9/NI8NmOpPl3zVNuBXzNpCaUvsEO4C0TwRJgc4JhaxqzbBOt01m2rZqZK7fNPUYztfvHn/eTFH+qLiii07gbZK4SJ8WJwv5jtJOM8lzdrgOmANRMgiw7VJChrrLPKFzyLAOf5/OOsSPa1cH4LIopsTbjTeLQOpEuPdJ4htwGervZnhWHFk8gJ5DJhdDtO8NOsYI1qUd9yzOTR3GOzpjDQOhniaRVXdAyYTXdPE7GpvUcD3wX6BTS3azpCVr4F5bJEJVWJN4lADKb63FaznK1pjP4iKWYTxs0iv/r5mv34xRAinU/YX7+1Un0HHrBMalMQyeLib2XIEuP8d/4O8rq5Gi3LP9Pp6dk0cAK93NkeS57YnHyu4RhEKUxz1RClqGrR3VT1VaAfQB25pUYDcmNeia0YbCZcnqd/sURwZBBHL+ja511Jg6dt6ZVFg6deW+qipKAObiqaRPz9Z2Q5bYHPHy4c/yO/1mmRZ9E1xzVW/S0JTqFuOjtD14uLLuDtoStfYhjx7ec61bDrC6NTedqIC7B09i/ajnfVa3F7qxRqkpdUwAHUNc3ljRGhRP5f6Fi4WSthFVMVhwOjdDBNylinSOQGB/ScOlpmWj6eBjqw/svyDgFhx7GgBeRo8pMHFSTpybkWume5FsdJnH6oJAGIjecPt63E8fj5szN3HIyYR7VyLIPwsGOLTpvQLxMW3KXo/N0X5cKsk+nJUykaqObuBY+tq4/2RvTWMNr8BdobnmQ==

Steps to reproduce

  1. create a sfc file and write input, v-model="form.a" and const form = reactive({a:"str"}) with the setup mode. it as a root app component.
  2. use "@vue/compiler-sfc" to get a js file of the app component.
  3. add the render function to compileScript functions 's output, such as
let __component: DefineComponent; // it is compileScript() 's output.
function render(_ctx, _cache){/*...*/} // it is compileTemplate() 's output.
__component.render = render
  1. createApp(__component).mount("#app");
  2. got the "Cannot read properties of undefined".

What is expected?

Render a <input /> with v-model.

What is actually happening?

Cannot read properties of undefined (reading 'value').

object _ctx of render(_ctx) does not has the form reactive.

System Info

System:
    OS: Windows 10 10.0.22621
    CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900HX
    Memory: 14.55 GB / 31.74 GB
  Binaries:
    Node: 20.3.1 - D:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.6.6 - D:\Program Files\nodejs\npm.CMD
    pnpm: 8.6.7 - ~\AppData\Roaming\npm\pnpm.CMD
  Browsers:
    Edge: Spartan (44.22621.2134.0), Chromium (115.0.1901.203)
    Internet Explorer: 11.0.22621.1

Any additional comments?

Use koa, @vue/compiler-sfc and babel, but do not include the Vite. Vite was too heavy, so instead of using it, I made my own loader using KoaController, @vue/compiler-sfc and babel.

Compile SFC file at run time, but all the browser receives is "text/javascrtpt".

 

There is a simplified version in SFC Playground

SFC code:

<template>
  <div>
    <input v-model="form.value" type="text" />
  </div>
</template>

<script lang="ts" setup>
import { reactive } from 'vue';

const form = reactive({
  value: 'str',
});
</script>

<style scoped lang="scss">
input {
  background-color: blue;
}
</style>

Full raw es6 javascript code in a html file:

import { vModelText as _vModelText, createElementVNode as _createElementVNode, withDirectives as _withDirectives, openBlock as _openBlock, createElementBlock as _createElementBlock } from "/oAuth/lib/vue";
import { defineComponent as _defineComponent } from "/oAuth/lib/vue";
import { reactive } from "/oAuth/lib/vue";
const __component = _defineComponent({
  setup(__props, {
    expose: __expose
  }) {
    __expose();
    const form = reactive({
      value: 'str'
    });
    const __returned__ = {
      form
    };
    Object.defineProperty(__returned__, '__isScriptSetup', {
      enumerable: false,
      value: true
    });
    return __returned__;
  }
});
export function render(_ctx, _cache) {
  return _openBlock(), _createElementBlock("div", null, [_withDirectives(_createElementVNode("input", {
    type: "text",
    "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => _ctx.form.value = $event)
  }, null, 512), [[_vModelText, _ctx.form.value]])]);
}
__component.__scopeId = "data-v-sfc18";
__component.render = render;
const onAppCreate = () => {};
const onBeforeAppCreate = () => {};
__component.appCreate = c => import("/oAuth/lib/vue").then(it => it.createApp(c));
;
export let app = void 0;
(async () => {
  let appCreate = __component.appCreate;
  if (!appCreate) appCreate = () => import("/oAuth/lib/vue").then(it => it.createApp(c));
  const app1 = await appCreate(__component);
  app = app1;
  app1.mount('#app');
})();
export default __component;
;
(url => {
  const styles = `input[data-v-sfc18] {
  background-color: blue;
}
`;
  let dom = document.head.querySelector(`style[data-url="${url}"]`);
  dom?.remove();
  dom = document.createElement('style');
  dom.setAttribute('data-url', url);
  dom.innerHTML = styles;
  document.head.append(dom);
})("/oAuth/test.a.vue");