Skip to content

definePageMeta try to process with ancorn ts code. Vue composables don't do so. #29790

@Maxttier

Description

@Maxttier

Environment

latest nuxt

Reproduction

async function getRouteMeta(contents, absolutePath) {
  if (!(absolutePath in pageContentsCache) || pageContentsCache[absolutePath] !== contents) {
    pageContentsCache[absolutePath] = contents;
    delete metaCache$1[absolutePath];
  }
  if (absolutePath in metaCache$1 && metaCache$1[absolutePath]) {
    return metaCache$1[absolutePath];
  }
  const loader = getLoader(absolutePath);
  const scriptBlocks = !loader ? null : loader === "vue" ? extractScriptContent(contents) : [{ code: contents, loader }];
  if (!scriptBlocks) {
    metaCache$1[absolutePath] = {};
    return {};
  }
  const extractedMeta = {};
  for (const script of scriptBlocks) {
    if (!PAGE_META_RE.test(script.code)) {
      continue;
    }
    const js = await transform(script.code, { loader: script.loader });
    throw new Error(js.code)
    const ast = parse(js.code, {
      sourceType: "module",
      ecmaVersion: "latest",
      ranges: true
    });
    const dynamicProperties = /* @__PURE__ */ new Set();
    let foundMeta = false;
    walk(ast, {
      enter(node) {
        if (foundMeta) {
          return;
        }
        if (node.type !== "ExpressionStatement" || node.expression.type !== "CallExpression" || node.expression.callee.type !== "Identifier" || node.expression.callee.name !== "definePageMeta") {
          return;
        }
        foundMeta = true;
        const pageMetaArgument = node.expression.arguments[0];
        for (const key of extractionKeys) {
          const property = pageMetaArgument.properties.find((property2) => property2.type === "Property" && property2.key.type === "Identifier" && property2.key.name === key);
          if (!property) {
            continue;
          }
          if (property.value.type === "ObjectExpression") {
            const valueString = js.code.slice(property.value.range[0], property.value.range[1]);
            try {
              extractedMeta[key] = JSON.parse(runInNewContext(`JSON.stringify(${valueString})`, {}));
            } catch {
              console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not JSON-serializable (reading \`${absolutePath}\`).`);
              dynamicProperties.add(key);
              continue;
            }
          }
          if (property.value.type === "ArrayExpression") {
            const values = [];
            for (const element of property.value.elements) {
              if (!element) {
                continue;
              }
              if (element.type !== "Literal" || typeof element.value !== "string") {
                console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not an array of string literals (reading \`${absolutePath}\`).`);
                dynamicProperties.add(key);
                continue;
              }
              values.push(element.value);
            }
            extractedMeta[key] = values;
            continue;
          }
          if (property.value.type !== "Literal" || typeof property.value.value !== "string" && typeof property.value.value !== "boolean") {
            console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`);
            dynamicProperties.add(key);
            continue;
          }
          extractedMeta[key] = property.value.value;
        }
        for (const property of pageMetaArgument.properties) {
          if (property.type !== "Property") {
            continue;
          }
          const isIdentifierOrLiteral = property.key.type === "Literal" || property.key.type === "Identifier";
          if (!isIdentifierOrLiteral) {
            continue;
          }
          const name = property.key.type === "Identifier" ? property.key.name : String(property.value);
          if (name) {
            dynamicProperties.add("meta");
            break;
          }
        }
        if (dynamicProperties.size) {
          extractedMeta.meta ?? (extractedMeta.meta = {});
          extractedMeta.meta[DYNAMIC_META_KEY] = dynamicProperties;
        }
      }
    });
  }
  metaCache$1[absolutePath] = extractedMeta;
  return extractedMeta;
}

Describe the bug

Ts code with decorators is passed to acorn.parse which can parse only js code. I see some plugins for ancorn to support ts!?

 const ast = parse(js.code, {
      sourceType: "module",
      ecmaVersion: "latest",
      ranges: true
    });

Additional context

No response

Logs

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions