Skip to content

Commit 261f007

Browse files
committed
Fixing a bug where the checksum would fail due to losing float precision
1 parent 8591379 commit 261f007

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

src/LiveComponent/src/LiveComponentHydrator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ private function calculateChecksum(array $dehydratedPropsData): ?string
257257
// sort so it is always consistent (frontend could have re-ordered data)
258258
ksort($dehydratedPropsData);
259259

260-
return base64_encode(hash_hmac('sha256', var_export($dehydratedPropsData, true), $this->secret, true));
260+
return base64_encode(hash_hmac('sha256', json_encode($dehydratedPropsData), $this->secret, true));
261261
}
262262

263263
private function verifyChecksum(array $identifierPops): void

src/LiveComponent/tests/Integration/LiveComponentHydratorTest.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ private function executeHydrationTestCase(callable $testFactory, int $minPhpVers
105105
}
106106

107107
$originalPropsToSend = $testCase->changedOriginalProps ?? $dehydratedProps->getProps();
108+
// mimic sending over the wire, which can subtle change php types
109+
$originalPropsToSend = json_decode(json_encode($originalPropsToSend), true);
108110

109111
$this->hydrator()->hydrate(
110112
$componentAfterHydration,
@@ -165,6 +167,25 @@ public function provideDehydrationHydrationTests(): iterable
165167
;
166168
}];
167169

170+
yield 'float: precision change to the frontend works ok' => [function () {
171+
return HydrationTest::create(new class() {
172+
#[LiveProp(writable: true)]
173+
public float $price;
174+
})
175+
// when the 123.00 float/double is json encoded, it becomes the
176+
// integer 123. If not handled correctly, this can cause a checksum
177+
// failure: the checksum is originally calculated with the float
178+
// 123.00, but then when the props are sent back to the server,
179+
// the float is converted to an integer 123, which causes the checksum
180+
// to fail.
181+
->mountWith(['price' => 123.00])
182+
->assertDehydratesTo(['price' => 123.00])
183+
->assertObjectAfterHydration(function (object $object) {
184+
$this->assertSame(123.00, $object->price);
185+
})
186+
;
187+
}];
188+
168189
yield 'DateTime: (de)hydrates correctly' => [function () {
169190
$date = new \DateTime('2023-03-05 9:23', new \DateTimeZone('America/New_York'));
170191

@@ -1042,7 +1063,7 @@ public function __construct()
10421063

10431064
$updatedProps = ['holdsDateAndEntity.product' => ['name' => 'new name']];
10441065

1045-
$result = $this->hydrator()->hydrate(
1066+
$this->hydrator()->hydrate(
10461067
$component,
10471068
$dehydratedProps->getProps(),
10481069
$updatedProps,

0 commit comments

Comments
 (0)