Skip to content

Commit

Permalink
Merge branch 'main' into content-layer
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic authored Aug 7, 2024
2 parents ede3610 + ea82b03 commit 59992a6
Show file tree
Hide file tree
Showing 30 changed files with 75 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-poems-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes internal server error when calling an Astro Action without arguments on Vercel.
2 changes: 2 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ export default [

// In some cases, using explicit letter-casing is more performant than the `i` flag
'regexp/use-ignore-case': 'off',
'regexp/prefer-regexp-exec': 'warn',
'regexp/prefer-regexp-test': 'warn',
},
},

Expand Down
Binary file added packages/astro/astro-4.13.1.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/astro/e2e/errors.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ test.describe('Error display', () => {
expect(fileExists).toBeTruthy();

const fileContent = await astro.readFile(absoluteFileUrl);
const lineNumber = absoluteFileLocation.match(/:(\d+):\d+$/)[1];
const lineNumber = /:(\d+):\d+$/.exec(absoluteFileLocation)[1];
const highlightedLine = fileContent.split('\n')[lineNumber - 1];
expect(highlightedLine).toContain(`@use '../styles/inexistent' as *;`);

Expand Down
3 changes: 0 additions & 3 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@
},
"./virtual-modules/*": "./dist/virtual-modules/*"
},
"imports": {
"#astro/*": "./dist/*.js"
},
"bin": {
"astro": "astro.js"
},
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/actions/runtime/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const onRequest = defineMiddleware(async (context, next) => {

// Heuristic: If body is null, Astro might've reset this for prerendering.
if (import.meta.env.DEV && request.method === 'POST' && request.body === null) {
// eslint-disable-next-line no-console
console.warn(
yellow('[astro:actions]'),
'POST requests should not be sent to prerendered pages. If you\'re using Actions, disable prerendering with `export const prerender = "false".'
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/actions/runtime/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const POST: APIRoute = async (context) => {
const contentType = request.headers.get('Content-Type');
const contentLength = request.headers.get('Content-Length');
let args: unknown;
if (contentLength === '0') {
if (!contentType || contentLength === '0') {
args = undefined;
} else if (contentType && hasContentType(contentType, formContentTypes)) {
args = await request.clone().formData();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
/* eslint-disable regexp/prefer-regexp-exec */
import type { IImage, ISize } from './interface.ts'
import { toUTF8String } from './utils.js'

Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ export class App {
}

#getDefaultStatusCode(routeData: RouteData, pathname: string): number {
if (!routeData.pattern.exec(pathname)) {
if (!routeData.pattern.test(pathname)) {
for (const fallbackRoute of routeData.fallbackRoutes) {
if (fallbackRoute.pattern.test(pathname)) {
return 302;
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ function getInvalidRouteSegmentError(
route: RouteData,
staticPath: GetStaticPathsItem
): AstroError {
const invalidParam = e.message.match(/^Expected "([^"]+)"/)?.[1];
const invalidParam = /^Expected "([^"]+)"/.exec(e.message)?.[1];
const received = invalidParam ? staticPath.params[invalidParam] : undefined;
let hint =
'Learn about dynamic routes at https://docs.astro.build/en/core-concepts/routing/#dynamic-routes';
Expand Down Expand Up @@ -421,7 +421,7 @@ async function generatePath(
// always be rendered
route.pathname !== '/' &&
// Check if there is a translated page with the same path
Object.values(options.allPages).some((val) => pathname.match(val.route.pattern))
Object.values(options.allPages).some((val) => val.route.pattern.test(pathname))
) {
return;
}
Expand Down Expand Up @@ -503,7 +503,7 @@ function getPrettyRouteName(route: RouteData): string {
} else if (route.component.includes('node_modules/')) {
// For routes from node_modules (usually injected by integrations),
// prettify it by only grabbing the part after the last `node_modules/`
return route.component.match(/.*node_modules\/(.+)/)?.[1] ?? route.component;
return /.*node_modules\/(.+)/.exec(route.component)?.[1] ?? route.component;
} else {
return route.component;
}
Expand Down
9 changes: 5 additions & 4 deletions packages/astro/src/core/errors/dev/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function enhanceViteSSRError({
// Vite has a fairly generic error message when it fails to load a module, let's try to enhance it a bit
// https://github.com/vitejs/vite/blob/ee7c28a46a6563d54b828af42570c55f16b15d2c/packages/vite/src/node/ssr/ssrModuleLoader.ts#L91
let importName: string | undefined;
if ((importName = safeError.message.match(/Failed to load url (.*?) \(resolved id:/)?.[1])) {
if ((importName = /Failed to load url (.*?) \(resolved id:/.exec(safeError.message)?.[1])) {
safeError.title = FailedToLoadModuleSSR.title;
safeError.name = 'FailedToLoadModuleSSR';
safeError.message = FailedToLoadModuleSSR.message(importName);
Expand All @@ -64,9 +64,10 @@ export function enhanceViteSSRError({
// Vite throws a syntax error trying to parse MDX without a plugin.
// Suggest installing the MDX integration if none is found.
if (
fileId &&
!renderers?.find((r) => r.name === '@astrojs/mdx') &&
safeError.message.match(/Syntax error/) &&
fileId?.match(/\.mdx$/)
/Syntax error/.test(safeError.message) &&
/.mdx$/.test(fileId)
) {
safeError = new AstroError({
...MdxIntegrationMissingError,
Expand All @@ -78,7 +79,7 @@ export function enhanceViteSSRError({

// Since Astro.glob is a wrapper around Vite's import.meta.glob, errors don't show accurate information, let's fix that
if (/Invalid glob/.test(safeError.message)) {
const globPattern = safeError.message.match(/glob: "(.+)" \(/)?.[1];
const globPattern = /glob: "(.+)" \(/.exec(safeError.message)?.[1];

if (globPattern) {
safeError.message = InvalidGlob.message(globPattern);
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/events/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface ConfigErrorEventPayload extends ErrorEventPayload {
*/
const ANONYMIZE_MESSAGE_REGEX = /^(?:\w| )+/;
function anonymizeErrorMessage(msg: string): string | undefined {
const matchedMessage = msg.match(ANONYMIZE_MESSAGE_REGEX);
const matchedMessage = ANONYMIZE_MESSAGE_REGEX.exec(msg);
if (!matchedMessage?.[0]) {
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class DevToolbarRadioCheckbox extends HTMLElement {

set radioStyle(value) {
if (!styles.includes(value)) {
// eslint-disable-next-line no-console
console.error(`Invalid style: ${value}, expected one of ${styles.join(', ')}.`);
return;
}
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/transitions/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ async function transition(
// This log doesn't make it worse than before, where we got error messages about uncaught exceptions, which can't be caught when the trigger was a click or history traversal.
// Needs more investigation on root causes if errors still occur sporadically
const err = e as Error;
// eslint-disable-next-line no-console
console.log('[astro]', err.name, err.message, err.stack);
}
}
Expand Down
9 changes: 6 additions & 3 deletions packages/astro/templates/actions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,18 @@ async function handleAction(param, path, context) {
let body = param;
if (!(body instanceof FormData)) {
try {
body = param ? JSON.stringify(param) : undefined;
body = JSON.stringify(param);
} catch (e) {
throw new ActionError({
code: 'BAD_REQUEST',
message: `Failed to serialize request body to JSON. Full error: ${e.message}`,
});
}
headers.set('Content-Type', 'application/json');
headers.set('Content-Length', body?.length.toString() ?? '0');
if (body) {
headers.set('Content-Type', 'application/json');
} else {
headers.set('Content-Length', '0');
}
}
const rawResult = await fetch(`/_actions/${path}`, {
method: 'POST',
Expand Down
23 changes: 21 additions & 2 deletions packages/astro/test/actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,18 +234,37 @@ describe('Astro Actions', () => {
});
});

it('Sets status to 204 when no content', async () => {
it('Sets status to 204 when content-length is 0', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': '0',
},
});
const res = await app.render(req);
assert.equal(res.status, 204);
});

it('Sets status to 204 when content-type is omitted', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
});
const res = await app.render(req);
assert.equal(res.status, 204);
});

it('Sets status to 415 when content-type is unexpected', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
body: 'hey',
headers: {
'Content-Type': 'text/plain',
},
});
const res = await app.render(req);
assert.equal(res.status, 415);
});

it('Is callable from the server with rewrite', async () => {
const req = new Request('http://example.com/rewrite');
const res = await app.render(req);
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/test/css-order-import.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ describe('CSS ordering - import order', () => {

const content = await Promise.all(getLinks(html).map((href) => getLinkContent(href)));
const css = content.map((c) => c.css).join('');
assert.equal(css.match(/\.astro-jsx/).length, 1, '.astro-jsx class is duplicated');
assert.equal(/\.astro-jsx/.exec(css).length, 1, '.astro-jsx class is duplicated');
});
});

Expand Down
4 changes: 2 additions & 2 deletions packages/astro/test/css-order.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ describe('CSS production ordering', () => {
assert.ok(content.length, 3, 'there are 3 stylesheets');
const [, sharedStyles, pageStyles] = content;

assert.ok(sharedStyles.css.match(/red/));
assert.ok(pageStyles.css.match(/#00f/));
assert.ok(/red/.exec(sharedStyles.css));
assert.ok(/#00f/.exec(pageStyles.css));
});

it('CSS injected by injectScript comes first because of import order', async () => {
Expand Down
6 changes: 4 additions & 2 deletions packages/astro/test/solid-component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ describe.skip('Solid component dev', { todo: 'Check why the test hangs.', skip:
const createHydrationScriptRegex = (flags) => new RegExp(/_\$HY=/, flags);

function countHydrationScripts(/** @type {string} */ html) {
// eslint-disable-next-line regexp/prefer-regexp-exec
return html.match(createHydrationScriptRegex('g'))?.length ?? 0;
}

function getFirstHydrationScriptLocation(/** @type {string} */ html) {
return html.match(createHydrationScriptRegex())?.index;
return createHydrationScriptRegex().exec(html)?.index;
}

/**
Expand All @@ -202,9 +203,10 @@ function countHydrationEvents(/** @type {string} */ html) {
// Number of times a component was hydrated during rendering
// We look for the hint "_$HY.r["

// eslint-disable-next-line regexp/prefer-regexp-exec
return html.match(createHydrationEventRegex('g'))?.length ?? 0;
}

function getFirstHydrationEventLocation(/** @type {string} */ html) {
return html.match(createHydrationEventRegex())?.index;
return createHydrationEventRegex().exec(html)?.index;
}
2 changes: 1 addition & 1 deletion packages/astro/test/ssr-api-route.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ describe('API routes in SSR', () => {

let count = 0;
let exp = /set-cookie:/g;
while (exp.exec(response)) {
while (exp.test(response)) {
count++;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/astro/test/units/i18n/astro_i18n.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { MissingLocale } from '#astro/core/errors/errors-data';
import { AstroError } from '#astro/core/errors/index';
import { toRoutingStrategy } from '#astro/i18n/utils';
import { validateConfig } from '../../../dist/core/config/validate.js';
import { MissingLocale } from '../../../dist/core/errors/errors-data.js';
import { AstroError } from '../../../dist/core/errors/index.js';
import {
getLocaleAbsoluteUrl,
getLocaleAbsoluteUrlList,
getLocaleRelativeUrl,
getLocaleRelativeUrlList,
} from '../../../dist/i18n/index.js';
import { toRoutingStrategy } from '../../../dist/i18n/utils.js';
import { parseLocale } from '../../../dist/i18n/utils.js';

describe('getLocaleRelativeUrl', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/create-astro/src/actions/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ async function verifyTemplate(tmpl: string, ref?: string) {
const GIT_RE = /^(?<repo>[\w.-]+\/[\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\w.-]+)?/;

function parseGitURI(input: string) {
const m = input.match(GIT_RE)?.groups;
const m = GIT_RE.exec(input)?.groups;
if (!m) throw new Error(`Unable to parse "${input}"`);
return {
repo: m.repo,
Expand Down
3 changes: 1 addition & 2 deletions packages/db/test/unit/column-queries.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,5 @@ describe('column queries', () => {

/** @param {string} query */
function getTempTableName(query) {
// eslint-disable-next-line regexp/no-unused-capturing-group
return query.match(/Users_([a-z\d]+)/)?.[0];
return /Users_[a-z\d]+/.exec(query)?.[0];
}
5 changes: 2 additions & 3 deletions packages/db/test/unit/reference-queries.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ describe('reference queries', () => {
});
});

/** @param {string | undefined} query */
/** @param {string} query */
function getTempTableName(query) {
// eslint-disable-next-line regexp/no-unused-capturing-group
return query.match(/User_([a-z\d]+)/)?.[0];
return /User_[a-z\d]+/.exec(query)?.[0];
}
4 changes: 2 additions & 2 deletions packages/integrations/markdoc/src/content-entry-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function raiseValidationErrors({
e.error.id !== 'variable-undefined' &&
// Ignore missing partial errors.
// We will resolve these in `resolvePartials`.
!(e.error.id === 'attribute-value-invalid' && e.error.message.match(/^Partial .+ not found/))
!(e.error.id === 'attribute-value-invalid' && /^Partial .+ not found/.test(e.error.message))
);
});

Expand Down Expand Up @@ -275,7 +275,7 @@ function getUsedTags(markdocAst: Node) {
// This is our signal that a tag is being used!
for (const { error } of validationErrors) {
if (error.id === 'tag-undefined') {
const [, tagName] = error.message.match(/Undefined tag: '(.*)'/) ?? [];
const [, tagName] = /Undefined tag: '(.*)'/.exec(error.message) ?? [];
tags.add(tagName);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async function compile(mdxCode, options) {
});
const code = result.toString();
// Capture the returned JSX code for testing
const jsx = code.match(/return (.+);\n\}\nexport default function MDXContent/s)?.[1];
const jsx = /return (.+);\n\}\nexport default function MDXContent/s.exec(code)?.[1];
if (jsx == null) throw new Error('Could not find JSX code in compiled MDX');
return dedent(jsx);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/node/src/serve-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function createStaticHandler(app: NodeApp, options: Options) {
break;
case 'always':
// trailing slash is not added to "subresources"
if (!hasSlash && !urlPath.match(isSubresourceRegex)) {
if (!hasSlash && !isSubresourceRegex.test(urlPath)) {
pathname = urlPath + '/' + (urlQuery ? '?' + urlQuery : '');
res.statusCode = 301;
res.setHeader('Location', pathname);
Expand Down
4 changes: 2 additions & 2 deletions packages/integrations/vue/src/editor.cts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function toTSX(code: string, className: string): string {

if (scriptSetup) {
const codeWithoutComments = scriptSetup.content.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, '');
const definePropsType = codeWithoutComments.match(/defineProps<([\s\S]+?)>\s?\(\)/);
const definePropsType = /defineProps<([\s\S]+?)>\s?\(\)/.exec(codeWithoutComments);
const propsGeneric = scriptSetup.attrs.generic;
const propsGenericType = propsGeneric ? `<${propsGeneric}>` : '';

Expand All @@ -41,7 +41,7 @@ export function toTSX(code: string, className: string): string {
// TODO. Find a way to support generics when using defineProps without passing explicit types.
// Right now something like this `defineProps({ prop: { type: Array as PropType<T[]> } })`
// won't be correctly typed in Astro.
const defineProps = codeWithoutComments.match(/defineProps\([\s\S]+?\)/);
const defineProps = /defineProps\([\s\S]+?\)/.exec(codeWithoutComments);
if (defineProps) {
result = `
import { defineProps } from 'vue';
Expand Down
4 changes: 2 additions & 2 deletions packages/markdown/remark/src/highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export async function highlightCodeBlocks(tree: Root, highlighter: Highlighter)
let languageMatch: RegExpMatchArray | null | undefined;
let { className } = node.properties;
if (typeof className === 'string') {
languageMatch = className.match(languagePattern);
languageMatch = languagePattern.exec(className);
} else if (Array.isArray(className)) {
for (const cls of className) {
if (typeof cls !== 'string') {
continue;
}

languageMatch = cls.match(languagePattern);
languageMatch = languagePattern.exec(cls);
if (languageMatch) {
break;
}
Expand Down
Loading

0 comments on commit 59992a6

Please sign in to comment.