astro 7.2.3 → 7.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,20 +46,25 @@ const HEIF = {
46
46
  const type = detectType(input, 8, metaBox.offset);
47
47
  const images = [];
48
48
  let currentOffset = ipcoBox.offset + 8;
49
- while (currentOffset < ipcoBox.offset + ipcoBox.size) {
49
+ const ipcoEnd = ipcoBox.offset + ipcoBox.size;
50
+ while (currentOffset < ipcoEnd) {
50
51
  const ispeBox = findBox(input, "ispe", currentOffset);
51
52
  if (!ispeBox) break;
53
+ if (ispeBox.size < 8) break;
54
+ if (ispeBox.offset + ispeBox.size > ipcoEnd) break;
52
55
  const rawWidth = readUInt32BE(input, ispeBox.offset + 12);
53
56
  const rawHeight = readUInt32BE(input, ispeBox.offset + 16);
54
57
  const clapBox = findBox(input, "clap", currentOffset);
55
58
  let width = rawWidth;
56
59
  let height = rawHeight;
57
- if (clapBox && clapBox.offset < ipcoBox.offset + ipcoBox.size) {
60
+ if (clapBox && clapBox.offset < ipcoEnd && clapBox.size >= 8) {
58
61
  const cropRight = readUInt32BE(input, clapBox.offset + 12);
59
62
  width = rawWidth - cropRight;
60
63
  }
61
64
  images.push({ height, width });
62
- currentOffset = ispeBox.offset + ispeBox.size;
65
+ const nextOffset = ispeBox.offset + ispeBox.size;
66
+ if (nextOffset <= currentOffset) break;
67
+ currentOffset = nextOffset;
63
68
  }
64
69
  if (images.length === 0) {
65
70
  throw new TypeError("Invalid HEIF, no sizes found");
@@ -1,6 +1,7 @@
1
1
  import { readUInt32BE, toUTF8String } from "./utils.js";
2
2
  const SIZE_HEADER = 4 + 4;
3
3
  const FILE_LENGTH_OFFSET = 4;
4
+ const MIN_ENTRY_LENGTH = 8;
4
5
  const ENTRY_LENGTH_OFFSET = 4;
5
6
  const ICON_TYPE_SIZE = {
6
7
  ICON: 32,
@@ -63,10 +64,17 @@ const ICNS = {
63
64
  let imageOffset = SIZE_HEADER;
64
65
  const images = [];
65
66
  while (imageOffset < fileLength && imageOffset < inputLength) {
67
+ if (inputLength - imageOffset < MIN_ENTRY_LENGTH) break;
66
68
  const imageHeader = readImageHeader(input, imageOffset);
69
+ const entryLength = imageHeader[1];
70
+ if (entryLength < MIN_ENTRY_LENGTH) break;
67
71
  const imageSize = getImageSize(imageHeader[0]);
68
- images.push(imageSize);
69
- imageOffset += imageHeader[1];
72
+ if (imageSize.width && imageSize.height) {
73
+ images.push(imageSize);
74
+ }
75
+ const nextOffset = imageOffset + entryLength;
76
+ if (nextOffset <= imageOffset) break;
77
+ imageOffset = nextOffset;
70
78
  }
71
79
  if (images.length === 0) {
72
80
  throw new TypeError("Invalid ICNS, no sizes found");
@@ -10,8 +10,8 @@ const JP2 = {
10
10
  },
11
11
  calculate(input) {
12
12
  const jp2hBox = findBox(input, "jp2h", 0);
13
- const ihdrBox = jp2hBox && findBox(input, "ihdr", jp2hBox.offset + 8);
14
- if (ihdrBox) {
13
+ const ihdrBox = jp2hBox && jp2hBox.size >= 8 && findBox(input, "ihdr", jp2hBox.offset + 8);
14
+ if (ihdrBox && ihdrBox.size >= 8) {
15
15
  return {
16
16
  height: readUInt32BE(input, ihdrBox.offset + 8),
17
17
  width: readUInt32BE(input, ihdrBox.offset + 12)
@@ -2,7 +2,7 @@ import { JXLStream } from "./jxl-stream.js";
2
2
  import { findBox, toUTF8String } from "./utils.js";
3
3
  function extractCodestream(input) {
4
4
  const jxlcBox = findBox(input, "jxlc", 0);
5
- if (jxlcBox) {
5
+ if (jxlcBox && jxlcBox.size >= 8) {
6
6
  return input.slice(jxlcBox.offset + 8, jxlcBox.offset + jxlcBox.size);
7
7
  }
8
8
  const partialStreams = extractPartialStreams(input);
@@ -17,10 +17,13 @@ function extractPartialStreams(input) {
17
17
  while (offset < input.length) {
18
18
  const jxlpBox = findBox(input, "jxlp", offset);
19
19
  if (!jxlpBox) break;
20
+ if (jxlpBox.size < 12) break;
20
21
  partialStreams.push(
21
22
  input.slice(jxlpBox.offset + 12, jxlpBox.offset + jxlpBox.size)
22
23
  );
23
- offset = jxlpBox.offset + jxlpBox.size;
24
+ const nextOffset = jxlpBox.offset + jxlpBox.size;
25
+ if (nextOffset <= offset) break;
26
+ offset = nextOffset;
24
27
  }
25
28
  return partialStreams;
26
29
  }
@@ -9,7 +9,7 @@ export declare const readUInt32BE: (input: Uint8Array, offset?: number) => numbe
9
9
  export declare const readUInt32LE: (input: Uint8Array, offset?: number) => number;
10
10
  export declare const readUInt64: (input: Uint8Array, offset: number, isBigEndian: boolean) => bigint;
11
11
  export declare function readUInt(input: Uint8Array, bits: 16 | 32, offset?: number, isBigEndian?: boolean): number;
12
- export declare function findBox(input: Uint8Array, boxName: string, currentOffset: number): {
12
+ export declare function findBox(input: Uint8Array, boxName: string, startOffset: number): {
13
13
  name: string;
14
14
  offset: number;
15
15
  size: number;
@@ -24,22 +24,36 @@ function readUInt(input, bits, offset = 0, isBigEndian = false) {
24
24
  const methodName = `readUInt${bits}${endian}`;
25
25
  return methods[methodName](input, offset);
26
26
  }
27
+ const MIN_BOX_HEADER = 8;
27
28
  function readBox(input, offset) {
28
- if (input.length - offset < 4) return;
29
+ if (input.length - offset < MIN_BOX_HEADER) return;
29
30
  const boxSize = readUInt32BE(input, offset);
31
+ if (boxSize === 0) {
32
+ return {
33
+ name: toUTF8String(input, offset + 4, offset + 8),
34
+ offset,
35
+ size: input.length - offset
36
+ };
37
+ }
38
+ if (boxSize === 1) return;
39
+ if (boxSize < MIN_BOX_HEADER) return;
30
40
  if (input.length - offset < boxSize) return;
31
41
  return {
32
- name: toUTF8String(input, 4 + offset, 8 + offset),
42
+ name: toUTF8String(input, offset + 4, offset + 8),
33
43
  offset,
34
44
  size: boxSize
35
45
  };
36
46
  }
37
- function findBox(input, boxName, currentOffset) {
38
- while (currentOffset < input.length) {
39
- const box = readBox(input, currentOffset);
47
+ function findBox(input, boxName, startOffset) {
48
+ let offset = startOffset;
49
+ while (offset < input.length) {
50
+ const box = readBox(input, offset);
40
51
  if (!box) break;
41
52
  if (box.name === boxName) return box;
42
- currentOffset += box.size > 0 ? box.size : 8;
53
+ if (box.size < MIN_BOX_HEADER) break;
54
+ const nextOffset = offset + box.size;
55
+ if (nextOffset <= offset) break;
56
+ offset = nextOffset;
43
57
  }
44
58
  }
45
59
  export {
@@ -1,6 +1,6 @@
1
1
  class BuildTimeAstroVersionProvider {
2
2
  // Injected during the build through esbuild define
3
- version = "7.2.3";
3
+ version = "7.2.4";
4
4
  }
5
5
  export {
6
6
  BuildTimeAstroVersionProvider
@@ -16,7 +16,7 @@ import { createConsoleLogger } from "../core/logger/impls/console.js";
16
16
  import { setLogger } from "../core/logger/manifest-logger.js";
17
17
  import { peekMiddleware } from "../core/middleware/load.js";
18
18
  import { getRouteTable } from "../core/routing/route-table.js";
19
- function createManifest(manifest, renderers, middleware) {
19
+ function createManifest(manifest, renderers, middleware, site) {
20
20
  function middlewareInstance() {
21
21
  return {
22
22
  onRequest: middleware ?? NOOP_MIDDLEWARE_FN
@@ -54,6 +54,7 @@ function createManifest(manifest, renderers, middleware) {
54
54
  componentMetadata: manifest?.componentMetadata ?? /* @__PURE__ */ new Map(),
55
55
  inlinedScripts: manifest?.inlinedScripts ?? /* @__PURE__ */ new Map(),
56
56
  i18n: manifest?.i18n,
57
+ site: site ?? manifest?.site,
57
58
  checkOrigin: false,
58
59
  allowedDomains: manifest?.allowedDomains ?? [],
59
60
  actionBodySizeLimit: 1024 * 1024,
@@ -93,9 +94,10 @@ class experimental_AstroContainer {
93
94
  streaming = false,
94
95
  manifest,
95
96
  renderers,
96
- resolve
97
+ resolve,
98
+ site
97
99
  }) {
98
- const ssrManifest = createManifest(manifest, renderers);
100
+ const ssrManifest = createManifest(manifest, renderers, void 0, site);
99
101
  const containerRenderers = renderers ?? manifest?.renderers ?? [];
100
102
  const containerResolve = async (specifier) => {
101
103
  if (this.#withManifest) {
@@ -133,12 +135,13 @@ class experimental_AstroContainer {
133
135
  * @param {AstroContainerOptions=} containerOptions
134
136
  */
135
137
  static async create(containerOptions = {}) {
136
- const { streaming = false, manifest, renderers = [], resolve } = containerOptions;
138
+ const { streaming = false, manifest, renderers = [], resolve, astroConfig } = containerOptions;
137
139
  return new experimental_AstroContainer({
138
140
  streaming,
139
141
  manifest,
140
142
  renderers,
141
- resolve
143
+ resolve,
144
+ site: astroConfig?.site ?? manifest?.site
142
145
  });
143
146
  }
144
147
  /**
@@ -196,7 +196,7 @@ ${contentConfig.error.message}`
196
196
  logger.info("Content config changed");
197
197
  shouldClear = true;
198
198
  }
199
- if (previousAstroVersion && previousAstroVersion !== "7.2.3") {
199
+ if (previousAstroVersion && previousAstroVersion !== "7.2.4") {
200
200
  logger.info("Astro version changed");
201
201
  shouldClear = true;
202
202
  }
@@ -204,8 +204,8 @@ ${contentConfig.error.message}`
204
204
  logger.info("Clearing content store");
205
205
  this.#store.clearAll();
206
206
  }
207
- if ("7.2.3") {
208
- this.#store.metaStore().set("astro-version", "7.2.3");
207
+ if ("7.2.4") {
208
+ this.#store.metaStore().set("astro-version", "7.2.4");
209
209
  }
210
210
  if (currentConfigDigest) {
211
211
  this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,7 +1,7 @@
1
1
  import {
2
- collapseDuplicateLeadingSlashes,
3
2
  prependForwardSlash,
4
- removeTrailingForwardSlash
3
+ removeTrailingForwardSlash,
4
+ stripRequestBase
5
5
  } from "@astrojs/internal-helpers/path";
6
6
  import { matchPattern } from "@astrojs/internal-helpers/remote";
7
7
  import { computePathnameFromDomain } from "../i18n/domain.js";
@@ -146,11 +146,7 @@ class BaseApp {
146
146
  updateRouteTable(this.manifest, newManifestData.routes);
147
147
  }
148
148
  removeBase(pathname) {
149
- pathname = collapseDuplicateLeadingSlashes(pathname);
150
- if (pathname.startsWith(this.manifest.base)) {
151
- return pathname.slice(this.baseWithoutTrailingSlash.length + 1);
152
- }
153
- return pathname;
149
+ return stripRequestBase(pathname, this.manifest.base);
154
150
  }
155
151
  /**
156
152
  * Decodes a pathname with `decodeURI`, falling back to the raw pathname when it
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "7.2.3";
1
+ const ASTRO_VERSION = "7.2.4";
2
2
  const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`;
3
3
  const ASTRO_ERROR_HEADER = "X-Astro-Error";
4
4
  const DEFAULT_404_COMPONENT = "astro-default-404.astro";
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
26
26
  await telemetry.record([]);
27
27
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
28
28
  const logger = restart.container.logger;
29
- const currentVersion = "7.2.3";
29
+ const currentVersion = "7.2.4";
30
30
  const isPrerelease = currentVersion.includes("-");
31
31
  if (!isPrerelease) {
32
32
  try {
@@ -1,9 +1,8 @@
1
1
  import colors from "piccolore";
2
2
  import {
3
- collapseDuplicateLeadingSlashes,
4
3
  collapseDuplicateSlashes,
5
4
  prependForwardSlash,
6
- removeTrailingForwardSlash
5
+ stripRequestBase
7
6
  } from "@astrojs/internal-helpers/path";
8
7
  import { deserializeActionResult } from "../../actions/runtime/client.js";
9
8
  import { createCallAction, createGetActionResult, hasActionPayload } from "../../actions/utils.js";
@@ -723,6 +722,9 @@ class FetchState {
723
722
  #stripHtmlExtension() {
724
723
  if (this.routeData && this.routeData.type === "page" && !routeHasHtmlExtension(this.routeData)) {
725
724
  this.pathname = this.pathname.replace(/\/index\.html$/, "/").replace(/\.html$/, "");
725
+ if (this.manifest.trailingSlash === "always" && this.pathname !== "" && !this.pathname.endsWith("/")) {
726
+ this.pathname += "/";
727
+ }
726
728
  }
727
729
  }
728
730
  #resolveRouteData() {
@@ -760,18 +762,12 @@ class FetchState {
760
762
  * Strips the manifest's base from a normalized request pathname and prepends
761
763
  * a forward slash.
762
764
  *
763
- * Mirrors `BaseApp.removeBase`, including the
764
- * `collapseDuplicateLeadingSlashes` fix that prevents middleware
765
- * authorization bypass when the URL starts with `//`.
765
+ * Mirrors `BaseApp.removeBase`: the router matches against this stripped path
766
+ * while middleware reads the un-stripped `context.url.pathname`, so both must
767
+ * strip the base identically.
766
768
  */
767
769
  #computePathname(normalizedPathname) {
768
- let pathname = collapseDuplicateLeadingSlashes(normalizedPathname);
769
- const base = this.manifest.base;
770
- if (pathname.startsWith(base)) {
771
- const baseWithoutTrailingSlash = removeTrailingForwardSlash(base);
772
- pathname = pathname.slice(baseWithoutTrailingSlash.length + 1);
773
- }
774
- return prependForwardSlash(pathname);
770
+ return prependForwardSlash(stripRequestBase(normalizedPathname, this.manifest.base));
775
771
  }
776
772
  /**
777
773
  * Decodes and normalizes the public request pathname before deriving the
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  appendForwardSlash,
3
- collapseDuplicateLeadingSlashes,
4
3
  joinPaths,
5
4
  prependForwardSlash,
6
- removeTrailingForwardSlash
5
+ removeTrailingForwardSlash,
6
+ stripRequestBase
7
7
  } from "@astrojs/internal-helpers/path";
8
8
  import { normalizeTheLocale } from "../../i18n/path.js";
9
9
  function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logger, pathnameFromRequest) {
@@ -32,13 +32,13 @@ function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logg
32
32
  }
33
33
  }
34
34
  if (locale) {
35
- const requestPathname = pathnameFromRequest ?? removeBase(url.pathname, base);
35
+ const requestPathname = pathnameFromRequest ?? stripRequestBase(url.pathname, base);
36
36
  pathname = prependForwardSlash(joinPaths(normalizeTheLocale(locale), requestPathname));
37
37
  if (trailingSlash === "always") {
38
38
  pathname = appendForwardSlash(pathname);
39
39
  } else if (trailingSlash === "never") {
40
40
  pathname = removeTrailingForwardSlash(pathname);
41
- } else if (requestPathname.endsWith("/")) {
41
+ } else if (url.pathname.endsWith("/")) {
42
42
  pathname = appendForwardSlash(pathname);
43
43
  }
44
44
  }
@@ -53,13 +53,6 @@ function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logg
53
53
  }
54
54
  return pathname;
55
55
  }
56
- function removeBase(pathname, base) {
57
- pathname = collapseDuplicateLeadingSlashes(pathname);
58
- if (pathname.startsWith(base)) {
59
- return pathname.slice(removeTrailingForwardSlash(base).length + 1);
60
- }
61
- return pathname;
62
- }
63
56
  export {
64
57
  computePathnameFromDomain
65
58
  };
@@ -270,7 +270,7 @@ function printHelp({
270
270
  message.push(
271
271
  linebreak(),
272
272
  ` ${bgGreen(black(` ${commandName} `))} ${green(
273
- `v${"7.2.3"}`
273
+ `v${"7.2.4"}`
274
274
  )} ${headline}`
275
275
  );
276
276
  }
@@ -1,19 +1,8 @@
1
- import {
2
- collapseDuplicateLeadingSlashes,
3
- prependForwardSlash,
4
- removeTrailingForwardSlash
5
- } from "@astrojs/internal-helpers/path";
1
+ import { prependForwardSlash, stripRequestBase } from "@astrojs/internal-helpers/path";
6
2
  import { computePathnameFromDomain } from "../i18n/domain.js";
7
3
  import { AstroIntegrationLogger } from "../logger/core.js";
8
4
  import { getLogger } from "../logger/manifest-logger.js";
9
5
  import { matchAllRoutes, matchRoute } from "./route-table.js";
10
- function removeBase(manifest, pathname) {
11
- pathname = collapseDuplicateLeadingSlashes(pathname);
12
- if (pathname.startsWith(manifest.base)) {
13
- return pathname.slice(removeTrailingForwardSlash(manifest.base).length + 1);
14
- }
15
- return pathname;
16
- }
17
6
  function safeDecodeURI(manifest, pathname) {
18
7
  try {
19
8
  return decodeURI(pathname);
@@ -36,7 +25,7 @@ function matchRequest(manifest, request, allowPrerenderedRoutes = false) {
36
25
  getLogger(manifest)
37
26
  );
38
27
  if (!pathname) {
39
- pathname = prependForwardSlash(removeBase(manifest, url.pathname));
28
+ pathname = prependForwardSlash(stripRequestBase(url.pathname, manifest.base));
40
29
  }
41
30
  const routeData = matchRoute(manifest, safeDecodeURI(manifest, pathname));
42
31
  if (!routeData) return void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "7.2.3",
3
+ "version": "7.2.4",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -153,15 +153,15 @@
153
153
  "xxhash-wasm": "^1.1.0",
154
154
  "yargs-parser": "^22.0.0",
155
155
  "zod": "^4.3.6",
156
- "@astrojs/internal-helpers": "0.10.3",
157
- "@astrojs/markdown-satteri": "0.3.6",
156
+ "@astrojs/internal-helpers": "0.10.4",
157
+ "@astrojs/markdown-satteri": "0.3.7",
158
158
  "@astrojs/telemetry": "3.3.3"
159
159
  },
160
160
  "optionalDependencies": {
161
161
  "sharp": "^0.34.0 || ^0.35.0"
162
162
  },
163
163
  "peerDependencies": {
164
- "@astrojs/markdown-remark": "7.2.3"
164
+ "@astrojs/markdown-remark": "7.2.4"
165
165
  },
166
166
  "peerDependenciesMeta": {
167
167
  "@astrojs/markdown-remark": {
@@ -194,7 +194,7 @@
194
194
  "undici": "^7.22.0",
195
195
  "vitest": "^4.1.0",
196
196
  "@astrojs/check": "0.9.10",
197
- "@astrojs/markdown-remark": "7.2.3",
197
+ "@astrojs/markdown-remark": "7.2.4",
198
198
  "astro-scripts": "0.0.14"
199
199
  },
200
200
  "engines": {