Skip to content

Commit

Permalink
fix: correctly serialize Infinity as island props
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic committed Oct 4, 2024
1 parent 657d197 commit 88ee1d1
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/beige-rice-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Support passing the values `Infinity` and `-Infinity` as island props.
8 changes: 7 additions & 1 deletion packages/astro/e2e/fixtures/pass-js/src/components/React.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ interface Props {
array: any[];
map: Map<string, string>;
set: Set<string>;
infinity: number;
negativeInfinity: number;
}

const isNode = typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]';

/** a counter written in React */
export default function Component({ undefined: undefinedProp, null: nullProp, boolean, number, string, bigint, object, array, map, set }: Props) {
export default function Component({ undefined: undefinedProp, null: nullProp, boolean, number, string, bigint, object, array, map, set, infinity, negativeInfinity }: Props) {
// We are testing hydration, so don't return anything in the server.
if(isNode) {
return <div></div>
Expand All @@ -30,6 +32,10 @@ export default function Component({ undefined: undefinedProp, null: nullProp, bo
<span id="boolean-value">{boolean.toString()}</span>
<span id="number-type">{Object.prototype.toString.call(number)}</span>
<span id="number-value">{number.toString()}</span>
<span id="infinity-type">{Object.prototype.toString.call(infinity)}</span>
<span id="infinity-value">{infinity.toString()}</span>
<span id="negative-infinity-type">{Object.prototype.toString.call(negativeInfinity)}</span>
<span id="negative-infinity-value">{negativeInfinity.toString()}</span>
<span id="string-type">{Object.prototype.toString.call(string)}</span>
<span id="string-value">{string}</span>
<span id="bigint-type">{Object.prototype.toString.call(bigint)}</span>
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/e2e/fixtures/pass-js/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ set.add('test2');
array={[0, "foo"]}
map={map}
set={set}
infinity={Infinity}
negativeInfinity={-Infinity}
/>
</main>
</body>
Expand Down
16 changes: 16 additions & 0 deletions packages/astro/e2e/pass-js.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ test.describe('Passing JS into client components', () => {
await expect(numberValue, 'is visible').toBeVisible();
await expect(numberValue).toHaveText('16');

const infinityType = page.locator('#infinity-type');
await expect(infinityType, 'is visible').toBeVisible();
await expect(infinityType).toHaveText('[object Number]');

const negativeInfinityType = page.locator('#negative-infinity-type');
await expect(negativeInfinityType, 'is visible').toBeVisible();
await expect(negativeInfinityType).toHaveText('[object Number]');

const infinityValue = page.locator('#infinity-value');
await expect(infinityValue, 'is visible').toBeVisible();
await expect(infinityValue).toHaveText('Infinity');

const negativeInfinityValue = page.locator('#negative-infinity-value');
await expect(negativeInfinityValue, 'is visible').toBeVisible();
await expect(negativeInfinityValue).toHaveText('-Infinity');

// string
const stringType = page.locator('#string-type');
await expect(stringType, 'is visible').toBeVisible();
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/runtime/server/astro-island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ declare const Astro: {
8: (value) => new Uint8Array(value),
9: (value) => new Uint16Array(value),
10: (value) => new Uint32Array(value),
11: (value) => Infinity * value,
};

// Not using JSON.parse reviver because it's bottom-up but we want top-down
Expand Down
13 changes: 10 additions & 3 deletions packages/astro/src/runtime/server/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const PROP_TYPE = {
Uint8Array: 8,
Uint16Array: 9,
Uint32Array: 10,
Infinity: 11,
};

function serializeArray(
Expand Down Expand Up @@ -93,11 +94,17 @@ function convertToSerializedForm(
default: {
if (value !== null && typeof value === 'object') {
return [PROP_TYPE.Value, serializeObject(value, metadata, parents)];
} else if (value === undefined) {
}
if (value === Infinity) {
return [PROP_TYPE.Infinity, 1];
}
if (value === -Infinity) {
return [PROP_TYPE.Infinity, -1];
}
if (value === undefined) {
return [PROP_TYPE.Value];
} else {
return [PROP_TYPE.Value, value];
}
return [PROP_TYPE.Value, value];
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions packages/astro/test/serialize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ describe('serialize', () => {
const output = `{"a":[10,[1,2,3]]}`;
assert.equal(serializeProps(input), output);
});
it('serializes Infinity and -Infinity', () => {
const input = { a: Infinity, b: -Infinity };
const output = `{"a":[11,1],"b":[11,-1]}`;
assert.equal(serializeProps(input), output);
})
it('cannot serialize a cyclic reference', () => {
const a = {};
a.b = a;
Expand Down

0 comments on commit 88ee1d1

Please sign in to comment.