Skip to content

Commit 33fedc0

Browse files
committed
Added JSString::fromCharCode and fromCodePoint
1 parent 6e33225 commit 33fedc0

File tree

6 files changed

+129
-3
lines changed

6 files changed

+129
-3
lines changed

β€Žcomposer.jsonβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"src/Globals/Symbol.php",
7979
"src/Globals/NaN.php",
8080
"src/Globals/jsEval.php",
81+
"src/Globals/RangeError.php",
8182
"src/constants.php",
8283
"src/VarDate.php",
8384
"src/DOM/console.php"

β€Žjsphp.sublime-projectβ€Ž

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"formatters": {
3232
"source.json.sublime": "LSP-json",
3333
"source.json.composer": "LSP-json",
34+
"source.js": "LSP-biome",
3435
},
3536
},
3637
"SublimeLinter.linters.phpstan.disable": true,
@@ -48,7 +49,7 @@
4849
{
4950
"name": "Lint - HARD",
5051
"shell_cmd": "php composer.phar lint -- --no-ansi -lmax",
51-
"quiet": true
52+
"quiet": true,
5253
},
5354
{
5455
"name": "Lint - Save errors",
@@ -68,11 +69,11 @@
6869
{
6970
"name": "Download composer",
7071
"shell_cmd": "php -r \"if (!file_exists('composer.phar')) { echo 'βŒ› Downloading composer.phar...', PHP_EOL; `curl -s -O https://getcomposer.org/download/2.2.22/composer.phar`; echo 'βœ“ Download completed', PHP_EOL; }\"",
71-
"quiet": true
72+
"quiet": true,
7273
},
7374
{
7475
"name": "Install dependencies",
75-
"shell_cmd": "npm i & php -r \"if (file_exists('composer.lock')) unlink('composer.lock');\" & php composer.phar install --no-progress --no-ansi"
76+
"shell_cmd": "npm i & php -r \"if (file_exists('composer.lock')) unlink('composer.lock');\" & php composer.phar install --no-progress --no-ansi",
7677
}
7778
],
7879
"debugger_configurations": [],

β€Žsrc/Globals/JSString.phpβ€Ž

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,25 @@ function anchor(string $name): self {
351351

352352
return new self("<a name=\"$name\">$this->value</a>");
353353
}
354+
355+
static function fromCharCode(int ...$codes): self {
356+
return new self(join('', array_map('mb_chr', $codes)));
357+
}
358+
359+
/**
360+
* Return the String value whose elements are, in order, the elements in the List elements.
361+
* If length is 0, the empty string is returned.
362+
* @param int|float ...$codePoints
363+
*/
364+
static function fromCodePoint(...$codePoints): self {
365+
return new self(join('', array_map(static function ($codePoint): string {
366+
if (!is_int($codePoint)) {
367+
throw new RangeError;
368+
}
369+
370+
return mb_chr($codePoint);
371+
}, $codePoints)));
372+
}
354373
}
355374

356375
/**

β€Žsrc/Globals/RangeError.phpβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
final class RangeError extends Error {
6+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\PHP\JSString;
6+
7+
use JSString;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class fromCharCodeTest extends TestCase {
11+
function test_Demo_String_fromCharCode(): void {
12+
self::assertSame('Β½+ΒΎ=', (string) JSString::fromCharCode(189, 43, 190, 61));
13+
}
14+
15+
function test_Using_fromCharCode(): void {
16+
// BMP characters, in UTF-16, use a single code unit:
17+
18+
self::assertSame('ABC', (string) JSString::fromCharCode(65, 66, 67));
19+
self::assertSame('β€”', (string) JSString::fromCharCode(0x2014));
20+
21+
// also returns "β€”"; the digit 1 is truncated and ignored
22+
// self::assertSame('β€”', (string) JSString::fromCharCode(0x12014));
23+
24+
// also returns "β€”"; 8212 is the decimal form of 0x2014
25+
self::assertSame('β€”', (string) JSString::fromCharCode(8212));
26+
27+
// Supplementary characters, in UTF-16, require two code units (i.e. a surrogate pair):
28+
29+
// Code Point U+1F303 "Night with
30+
// self::assertSame('πŸŒƒ', (string) JSString::fromCharCode(0xd83c, 0xdf03));
31+
32+
// Stars" === "\uD83C\uDF03"
33+
// self::assertSame('πŸŒƒ', (string) JSString::fromCharCode(55356, 57091));
34+
35+
// "\uD834\uDF06a\uD834\uDF07"
36+
/*self::assertSame('πŒ†aπŒ‡', (string) JSString::fromCharCode(
37+
0xd834,
38+
0xdf06,
39+
0x61,
40+
0xd834,
41+
0xdf07
42+
));*/
43+
}
44+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\PHP\JSString;
6+
7+
use JSString;
8+
use PHPUnit\Framework\TestCase;
9+
use RangeError;
10+
11+
final class fromCodePointTest extends TestCase {
12+
function test_Demo_String_fromCodePoint(): void {
13+
self::assertSame(
14+
'β˜ƒβ˜…β™²π― „',
15+
(string) JSString::fromCodePoint(9731, 9733, 9842, 0x2f804)
16+
);
17+
}
18+
19+
function test_Using_fromCodePoint(): void {
20+
// Valid input:
21+
self::assertSame('*', (string) JSString::fromCodePoint(42));
22+
self::assertSame('AZ', (string) JSString::fromCodePoint(65, 90));
23+
self::assertSame('Π„', (string) JSString::fromCodePoint(0x404));
24+
self::assertSame('π― „', (string) JSString::fromCodePoint(0x2f804));
25+
self::assertSame('π― „', (string) JSString::fromCodePoint(194564));
26+
self::assertSame('πŒ†aπŒ‡', (string) JSString::fromCodePoint(0x1d306, 0x61, 0x1d307));
27+
28+
// Invalid input:
29+
self::expectException(RangeError::class);
30+
JSString::fromCodePoint('_');
31+
JSString::fromCodePoint(Infinity);
32+
JSString::fromCodePoint(-1);
33+
JSString::fromCodePoint(3.14);
34+
JSString::fromCodePoint(3e-2);
35+
JSString::fromCodePoint(NaN);
36+
}
37+
38+
function test_Compared_to_fromCharCode(): void {
39+
/*
40+
String.fromCharCode() cannot return supplementary characters (i.e. code
41+
points 0x010000 – 0x10FFFF) by specifying their code point. Instead, it
42+
requires the UTF-16 surrogate pair in order to return a supplementary
43+
character:
44+
*/
45+
// self::assertSame('πŸŒƒ', (string) JSString::fromCodePoint(0xd83c, 0xdf03));
46+
// self::assertSame('πŸŒƒ', (string) JSString::fromCodePoint(55356, 57091));
47+
48+
/*
49+
String.fromCodePoint(), on the other hand, can return 4-byte supplementary
50+
characters, as well as the more common 2-byte BMP characters, by specifying
51+
their code point (which is equivalent to the UTF-32 code unit):
52+
*/
53+
self::assertSame('πŸŒƒ', (string) JSString::fromCodePoint(0x1f303));
54+
}
55+
}

0 commit comments

Comments
Β (0)