Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Add js() helper #39389

Merged
merged 16 commits into from
Nov 3, 2021
Merged

[8.x] Add js() helper #39389

merged 16 commits into from
Nov 3, 2021

Conversation

tanthammar
Copy link
Contributor

@tanthammar tanthammar commented Oct 27, 2021

Using the @json directive within component tags is currently not supported by Laravel.
For example, <x-alert :errors="@json($errors->all())"/> will not be compiled.

  • This PR adds a js() helper to use in blade components or anywhere in php.
  • The helper has $options and $depth, following the existing @json() directive.
  • It is useful for any blade file with inline Js as it handles more cases than the @json() directive.
  • It handles objects, arrays and strings, else, falls back to json_encode()
  • The helper is inspired by the Livewire @js directive, creds' to @calebporzio

Why we need this:

Lets say we have a blade component; button.blade.php

<button {{ $attributes->merge(['class' => 'classes']) }}>
{{ $slot }}
</button>

If we want to add Alpine interactivity we cannot use the Laravel @json directive, as it won't compile.

<x-button x-data
   x-on:click="$dispatch( 'notify-errors', @json($errors->all()) )"
   type="submit"> Submit </x-button>

With this js() helper we will be able to work around it.

<x-button x-data
   x-on:click="$dispatch( 'notify-errors', {{ js($errors->all()) }} )"
   type="submit"> Submit </x-button>

The helper is chainable in js.

<x-foo x-data="{ 
    keys: {{ js($someArray) }}.keys() 
}"/>

You don't have to add surrounding quotes

<x-foo x-data="{ 
    foo: {{ js($fn_returning_a_string()) }} 
}"/>

Optional flags and depth parameters.

<x-foo x-data="{ 
    foo: {{ js($complexNestedArray, JSON_NUMERIC_CHECK | JSON_FORCE_OBJECT, 8) }} 
}"/>

@GrahamCampbell
Copy link
Member

Nice idea, as long as people are super careful with XSS.

@tanthammar
Copy link
Contributor Author

@GrahamCampbell
That is not my forte :) so, I don't understand ...
What is the difference from using the existing @json() directive?

I mean, why is
x-data="{ foo: @json($array) }"
a lesser security risk than
x-data="{ foo: {{ js($array) }} }"?

@tanthammar
Copy link
Contributor Author

I don't know how to please the StyleCI, it says to add spacing rows and then complaints for them to be removed ...

@derekmd
Copy link
Contributor

derekmd commented Oct 27, 2021

That StyleCI feedback is confusing.

  • Another blank line needs to be added between the two if blocks.
  • Docblock line @return string should also be added.

@shadoWalker89
Copy link
Contributor

@tanthammar For the StyleCi you can just download the "Download raw diff" button and apply using git as a patch.
Than you can add another commit with the changes (or maybe amend if you do not want to add another commit) and push your local branch to github.

@driesvints
Copy link
Member

@tanthammar I fixed those StyleCI issues for you 👍

@calebporzio
Copy link
Contributor

Weighing in here, We added @js to Livewire recently and everything is going pretty well. Tina is right that @js restricts usage in bindings etc... and having a helper in the global namespace would be nice.

My only nitpick with this is that the method signature (accepting options and depth) doesn't match the Blade directive and that might be confusing for some.

Otherwise, looks good, but needs tests (which can be copied from Livewire) @tanthammar.

@tanthammar
Copy link
Contributor Author

@calebporzio I added tests in the PR, Livewire repo. Don't know where to put them here.

@taylorotwell
Copy link
Member

Can you link me to the tests in the Livewire repo?

@tanthammar
Copy link
Contributor Author

@taylorotwell https://github.com/livewire/livewire/pull/4108/files

@tanthammar
Copy link
Contributor Author

tanthammar commented Oct 29, 2021

My only nitpick with this is that the method signature (accepting options and depth) doesn't match the Blade directive and that might be confusing for some.

The Laravel @json() directive has the same signature. Which would imply that Livewire could use the same.
Or, maybe I misunderstood.

@taylorotwell
Copy link
Member

taylorotwell commented Oct 29, 2021

My main hesitation with this PR was adding a js helper to the global namespace since that is such a commonly used abbreviation in web development and it's likely other apps have defined a helper like this for their own purposes.

I moved the method to a new Js class (that only contains this method for now). We would add a facade entry for this:

'Js' => Illuminate\Support\Js::class,

Usage looks like:

<div something="{{ Js::from(['foo' => 'bar']) }}">
    Hi
</div>

Thoughts?

@tanthammar
Copy link
Contributor Author

I agree with your opinion and I think it aligns better with other helpers like Str::from.

@tanthammar
Copy link
Contributor Author

tanthammar commented Oct 29, 2021

Also maybe move code from the @JSON() directive into the Js class (an additional method), to keep JavaScript related things in the same file just like the Str helpers?

Naming is harder...

Js::encode or Js::json for the current @JSON and Js::parse or Js::from for this.

It's great if it's clear that @JSON isn't the same as Js::from.

In my head I think of them as Js::encode and Js::parse.

Sorry if I'm not giving helpful feedback.

@derekmd
Copy link
Contributor

derekmd commented Oct 29, 2021

Is the string conditional supposed to be for raw JavaScript already built in PHP? Or does the function's string conditional block also need handling for JavaScript's \ escape character?

$foo = '\\';
// 1 character-length PHP string, human-readable in Laravel Tinker => "\" 

Js::from($foo);
// => "'\'"

echo Js::from($foo);

prints JavaScript:

'\'

Which is an syntax error in JavaScript. The second ' character is escaped so it expects another ' character for '\'' to close the string expression. Another example:

echo Js::from('\\nested\\path');

prints JavaScript:

'\nested\path'

n and p are attempted to be escaped. \n is a newline and \p isn't a special character so it's treated normally as two characters.


Changing to:

if (is_string($expression)) {
    return "'".str_replace("'", "\'", str_replace('\\', '\\\\', $expression))."'";
}
echo Js::from('\\nested\\path');

becomes JavaScript:

'\\nested\\path'

for human-readable value \nested\path.

Or should json_encode() be called on strings like the other primitive types are treated? Unless I'm misunderstanding Livewire's use case.

@tanthammar
Copy link
Contributor Author

tanthammar commented Oct 30, 2021

Is the string conditional supposed to be for raw JavaScript already built in PHP?

@derekmd No, it is intended to compile PHP object, array, boolean or string

@taylorotwell
Copy link
Member

@derekmd did you still have any concerns or questions about this?

@derekmd
Copy link
Contributor

derekmd commented Nov 1, 2021

@taylorotwell: the JavaScript escape character \ still needs to be addressed when encoding strings. I assume json_encode() isn't used to avoid wrapping the HTML attribute value in " quotes. The str_replace() calls I suggested should work.

The below example component should show phrase \nested\path in an alert but currently it instead shows <new line> + ested\path due to partially-encoded JavaScript.

App\View\Components\ButtonJs.php

namespace App\View\Components;

use Illuminate\View\Component;

class ButtonJs extends Component
{
    public function render()
    {
        return view('components.button-js');
    }
}

resources/views/components/button-js.blade.php

<button type="button" onclick="data = {!! $attributes['x-data'] !!}; alert(data.foo);">
    Show alert JS
</button>

resources/views/welcome.blade.php

<x-button-js x-data="{ foo: {{ \Illuminate\Support\Js::from('\\nested\\path') }} }" />

Updated method:

public static function from($expression, $options = null, $depth = 512)
{
    if (is_object($expression) || is_array($expression)) {
        $base64 = base64_encode(json_encode($expression, $options, $depth));

        return "JSON.parse(atob('{$base64}'))";
    }

    if (is_string($expression)) {
        return "'".str_replace("'", "\'", str_replace('\\', '\\\\', $expression))."'";
    }

    return json_encode($expression, $options, $depth);
}

@taylorotwell
Copy link
Member

@tanthammar any thoughts?

@tanthammar
Copy link
Contributor Author

@taylorotwell apart from my comments earlier on naming, I updated to a more simplified solution that should cover most cases of Javascripts need for escaping characters in strings.

I tested these:

$expression = "///path///path";
> '\/\/\/path\/\/\/path'

$expression = "\path\path";
> '\\path\\path'

$expression = "\\path\\path";
> "\path\path"

@derekmd can you confirm?

@tanthammar
Copy link
Contributor Author

tanthammar commented Nov 2, 2021

@taylorotwell Ok, here is my take on this.

I renamed Js class to Json because there is an existing @json directive and CompilesJson trait, and we are using json_encode() in various ways.

  • I added some more methods and directives, named in a descriptive manner.
  • All the blade directives refer to the Json class, for easier maintenance.
  • Added tests for the Json class methods.

Json class

Json::parse() //generates single-quoted Javascript objects, arrays and strings
Json::encode() //generates double-quoted Javascript objects, arrays and strings, used by @json()
Json::bool() //php boolean to Javascript true/false, without quotes
Json::str() //generates Javascript single-quoted strings

Blade directives

@json() //kept for legacy reasons, does the same as @jsonEncode()
@jsonEncode()
@jsonParse()
@jsonBool()
@jsonStr()

@driesvints
Copy link
Member

@tanthammar tests seem to fail now

@tanthammar
Copy link
Contributor Author

@driesvints Yes I see that. It works locally for me. But I'm on php 8... Or because I renamed the class?

@driesvints
Copy link
Member

driesvints commented Nov 2, 2021

Think you just need to adjust the tests to the newly expected output?

Edit: urgh this output -.-

1) Illuminate\Tests\View\Blade\BladeJsonTest::testStatementIsCompiledWithSafeDefaultEncodingOptions
129
Failed asserting that two strings are equal.
130
--- Expected
131
+++ Actual
132
@@ @@
133
-'var foo = <?php echo json_encode($var, 15, 512) ?>;'
134
+'var foo = <?php echo Illuminate\Support\Json::encode(($var)) ?>;'
135

136
/home/runner/work/framework/framework/tests/View/Blade/BladeJsonTest.php:12
137

138
2) Illuminate\Tests\View\Blade\BladeJsonTest::testEncodingOptionsCanBeOverwritten
139
Failed asserting that two strings are equal.
140
--- Expected
141
+++ Actual
142
@@ @@
143
-'var foo = <?php echo json_encode($var, JSON_HEX_TAG, 512) ?>;'
144
+'var foo = <?php echo Illuminate\Support\Json::encode(($var, JSON_HEX_TAG)) ?>;'
145

146
/home/runner/work/framework/framework/tests/View/Blade/BladeJsonTest.php:20

@tanthammar
Copy link
Contributor Author

@driesvints Ah, didn't know that file existed.

@taylorotwell
Copy link
Member

taylorotwell commented Nov 2, 2021

Sorry - can we go back to the simpler PR we had before without adding any additional Blade directives, etc? I like to take things one step at a time. I was just curious your feedback about @derekmd's string concerns. No need to rename the class or add any additional directives at this point.

@tanthammar
Copy link
Contributor Author

Ok, no problems.

How about naming the class Json, for future methods?

And, can I keep the forwarding of the json blade directive to the new class method?

Do you want to keep the ::from name or do you like the ::encode and ::parse names?

@taylorotwell
Copy link
Member

Personally I kinda liked the Js::from method.

@tanthammar
Copy link
Contributor Author

Yes sir ;) I'll revert it!


if (is_string($expression)) {
return str_replace('"', "'", json_encode($expression));
}
Copy link
Contributor

@derekmd derekmd Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks for any string containing a single quote character.

str_replace('"', "'", json_encode("'"));
// PHP "'''"
// JavaScript '''
//     Invalid syntax since single quotes '' represent 1 single quote escaped.
//     Another single quote is required to close the expression: ''''

Use one of:

  1. json_encode($expression) without any secondary str_replace() calls
    • Blade {{ }} -> e() HTML encode any single or double quote characters.

      Blade template for the component from my earlier comment:

      @php
          $foo = '"\'';
      @endphp
      <x-button-js x-data="{ foo: {{ \Illuminate\Support\Js::from($foo) }} }">
          Show alert JS
      </x-button-js>

      HTML result:

      <button x-data="{ foo: &quot;\&quot;&#039;&quot; }"
              type="button"
              onclick="data = { foo: &quot;\&quot;&#039;&quot; }; alert(data.foo);">
          Show alert JS
      </button>
  2. "'".str_replace("'", "\'", str_replace('\\', '\\\\', $expression))."'" that was suggested earlier

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change to your suggestion.

if (is_object($expression) || is_array($expression)) {
$base64 = base64_encode(json_encode($expression, $options, $depth));

return "JSON.parse(atob('{$base64}'))";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line feels a bit of a hack to make it work with Alpine.js and only serves the cause of Alpine.js imho.

Can't it be made to work like a regular json_encode such that the output for

<x-button x-data
   x-on:click="$dispatch( 'notify-errors', {{ js($errors->all()) }} )"
   type="submit"> Submit </x-button>

becomes simply an actual (correctly escaped if needed) javascript object like so:

...
x-on:click="$dispatch( 'notify-errors', { someNumber: 5, someProp: [1,2,3] } )"
...

That would simplify this problem a lot since it directly aligns with the usage of @json.

Ofcourse it would be great if @json Blade directives (and others) could just be made to work but I guess thats a whole other issue.

Copy link
Contributor

@derekmd derekmd Nov 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specific to that $errors code snippet, the https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/ViewErrorBag.php class could be updated to meet PHP's JsonSerializable interface.

<!-- MessageBag@jsonSerialize() exists so this already works -->
<x-button x-on:click="$dispatch('notify-errors', {{ json_encode($errors->getBag('default')) }})" />
// new method on ViewErrorBag
public function jsonSerialize()
{
    return array_map(function (MessageBag $bag) {
        return $bag->jsonSerialize();
    }, $this->bags);
}
<x-button x-on:click="$dispatch('notify-errors', {{ json_encode($errors) }})" />

Personally, to serialize PHP for Vue JS components I added a custom Blade directive that invoked a simplified class derived from package "laracasts/utilities": https://github.com/laracasts/PHP-Vars-To-Js-Transformer/blob/1764a14305100ab2f2bea3e3197ff3400b4e66d7/src/Transformers/Transformer.php#L96.

Methods jsonSerialize() & toJson() should cover most uses. It's only a matter of if you don't own the class being serialized. e.g., from "laravel/framework" or a 3rd-party package.

Copy link
Contributor Author

@tanthammar tanthammar Nov 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that json_encode returns double-quoted js.
You can't use it in any html data-foo="...". It's not just for Alpine, applicable for Vue as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not looked into specifics for Alpine, but in Vue I can just use <my-component :some-data='@json($data)' />, note the single quotes. This works in every case, including for all kinds of quotes and characters inside your json strings. It helps that the default @json options default to JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT.

@tanthammar
Copy link
Contributor Author

@taylorotwell
I have reverted back to Js:from with changes suggested by @derekmd

@inxilpro
Copy link
Contributor

inxilpro commented Nov 3, 2021

Three comments:

  1. We definitely have a js() helper in our project, so I think the call to find a different name was the right one
  2. We have a slightly more involved JsString implementation that avoids the atob() call. You can see it in this gist — in benchmarks, the proposed implementation here is about 70% slower than our JsString implementation.
  3. I prefer the name JsString as it pairs well with HtmlString

Benchmarks

image

You can run this benchmark on https://jsbench.me/

JsString

// Short array (20 items)
JSON.parse('[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]');

// Long array (2000 items)
JSON.parse('[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000]');

// Typical User object
JSON.parse('{\u0022id\u0022:1,\u0022given_name\u0022:\u0022Test\u0022,\u0022family_name\u0022:\u0022User\u0022,\u0022suffix\u0022:null,\u0022display_name\u0022:\u0022System\u0022,\u0022legal_name\u0022:\u0022System\u0022,\u0022username\u0022:\u0022test\u0022,\u0022role\u0022:\u0022guest\u0022,\u0022email\u0022:\[email protected]\u0022,\u0022email2\u0022:null,\u0022photo\u0022:null,\u0022avatar_upload_id\u0022:null,\u0022locale\u0022:\u0022en\u0022,\u0022timezone\u0022:\u0022America\\\/New_York\u0022,\u0022latitude\u0022:null,\u0022longitude\u0022:null,\u0022confirmed\u0022:true,\u0022created_at\u0022:\u00221997-01-01 00:00:00\u0022,\u0022updated_at\u0022:\u00221997-01-01 00:00:00\u0022,\u0022account_id\u0022:1,\u0022public_id\u0022:null,\u0022aggregate_role\u0022:\u0022guest\u0022}');

Js

// Short array (20 items)
JSON.parse(atob('WzEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwXQ=='));

// Long array (2000 items)
JSON.parse(atob('WzEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIzLDI0LDI1LDI2LDI3LDI4LDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLDYyLDYzLDY0LDY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDc4LDc5LDgwLDgxLDgyLDgzLDg0LDg1LDg2LDg3LDg4LDg5LDkwLDkxLDkyLDkzLDk0LDk1LDk2LDk3LDk4LDk5LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDExOCwxMTksMTIwLDEyMSwxMjIsMTIzLDEyNCwxMjUsMTI2LDEyNywxMjgsMTI5LDEzMCwxMzEsMTMyLDEzMywxMzQsMTM1LDEzNiwxMzcsMTM4LDEzOSwxNDAsMTQxLDE0MiwxNDMsMTQ0LDE0NSwxNDYsMTQ3LDE0OCwxNDksMTUwLDE1MSwxNTIsMTUzLDE1NCwxNTUsMTU2LDE1NywxNTgsMTU5LDE2MCwxNjEsMTYyLDE2MywxNjQsMTY1LDE2NiwxNjcsMTY4LDE2OSwxNzAsMTcxLDE3MiwxNzMsMTc0LDE3NSwxNzYsMTc3LDE3OCwxNzksMTgwLDE4MSwxODIsMTgzLDE4NCwxODUsMTg2LDE4NywxODgsMTg5LDE5MCwxOTEsMTkyLDE5MywxOTQsMTk1LDE5NiwxOTcsMTk4LDE5OSwyMDAsMjAxLDIwMiwyMDMsMjA0LDIwNSwyMDYsMjA3LDIwOCwyMDksMjEwLDIxMSwyMTIsMjEzLDIxNCwyMTUsMjE2LDIxNywyMTgsMjE5LDIyMCwyMjEsMjIyLDIyMywyMjQsMjI1LDIyNiwyMjcsMjI4LDIyOSwyMzAsMjMxLDIzMiwyMzMsMjM0LDIzNSwyMzYsMjM3LDIzOCwyMzksMjQwLDI0MSwyNDIsMjQzLDI0NCwyNDUsMjQ2LDI0NywyNDgsMjQ5LDI1MCwyNTEsMjUyLDI1MywyNTQsMjU1LDI1NiwyNTcsMjU4LDI1OSwyNjAsMjYxLDI2MiwyNjMsMjY0LDI2NSwyNjYsMjY3LDI2OCwyNjksMjcwLDI3MSwyNzIsMjczLDI3NCwyNzUsMjc2LDI3NywyNzgsMjc5LDI4MCwyODEsMjgyLDI4MywyODQsMjg1LDI4NiwyODcsMjg4LDI4OSwyOTAsMjkxLDI5MiwyOTMsMjk0LDI5NSwyOTYsMjk3LDI5OCwyOTksMzAwLDMwMSwzMDIsMzAzLDMwNCwzMDUsMzA2LDMwNywzMDgsMzA5LDMxMCwzMTEsMzEyLDMxMywzMTQsMzE1LDMxNiwzMTcsMzE4LDMxOSwzMjAsMzIxLDMyMiwzMjMsMzI0LDMyNSwzMjYsMzI3LDMyOCwzMjksMzMwLDMzMSwzMzIsMzMzLDMzNCwzMzUsMzM2LDMzNywzMzgsMzM5LDM0MCwzNDEsMzQyLDM0MywzNDQsMzQ1LDM0NiwzNDcsMzQ4LDM0OSwzNTAsMzUxLDM1MiwzNTMsMzU0LDM1NSwzNTYsMzU3LDM1OCwzNTksMzYwLDM2MSwzNjIsMzYzLDM2NCwzNjUsMzY2LDM2NywzNjgsMzY5LDM3MCwzNzEsMzcyLDM3MywzNzQsMzc1LDM3NiwzNzcsMzc4LDM3OSwzODAsMzgxLDM4MiwzODMsMzg0LDM4NSwzODYsMzg3LDM4OCwzODksMzkwLDM5MSwzOTIsMzkzLDM5NCwzOTUsMzk2LDM5NywzOTgsMzk5LDQwMCw0MDEsNDAyLDQwMyw0MDQsNDA1LDQwNiw0MDcsNDA4LDQwOSw0MTAsNDExLDQxMiw0MTMsNDE0LDQxNSw0MTYsNDE3LDQxOCw0MTksNDIwLDQyMSw0MjIsNDIzLDQyNCw0MjUsNDI2LDQyNyw0MjgsNDI5LDQzMCw0MzEsNDMyLDQzMyw0MzQsNDM1LDQzNiw0MzcsNDM4LDQzOSw0NDAsNDQxLDQ0Miw0NDMsNDQ0LDQ0NSw0NDYsNDQ3LDQ0OCw0NDksNDUwLDQ1MSw0NTIsNDUzLDQ1NCw0NTUsNDU2LDQ1Nyw0NTgsNDU5LDQ2MCw0NjEsNDYyLDQ2Myw0NjQsNDY1LDQ2Niw0NjcsNDY4LDQ2OSw0NzAsNDcxLDQ3Miw0NzMsNDc0LDQ3NSw0NzYsNDc3LDQ3OCw0NzksNDgwLDQ4MSw0ODIsNDgzLDQ4NCw0ODUsNDg2LDQ4Nyw0ODgsNDg5LDQ5MCw0OTEsNDkyLDQ5Myw0OTQsNDk1LDQ5Niw0OTcsNDk4LDQ5OSw1MDAsNTAxLDUwMiw1MDMsNTA0LDUwNSw1MDYsNTA3LDUwOCw1MDksNTEwLDUxMSw1MTIsNTEzLDUxNCw1MTUsNTE2LDUxNyw1MTgsNTE5LDUyMCw1MjEsNTIyLDUyMyw1MjQsNTI1LDUyNiw1MjcsNTI4LDUyOSw1MzAsNTMxLDUzMiw1MzMsNTM0LDUzNSw1MzYsNTM3LDUzOCw1MzksNTQwLDU0MSw1NDIsNTQzLDU0NCw1NDUsNTQ2LDU0Nyw1NDgsNTQ5LDU1MCw1NTEsNTUyLDU1Myw1NTQsNTU1LDU1Niw1NTcsNTU4LDU1OSw1NjAsNTYxLDU2Miw1NjMsNTY0LDU2NSw1NjYsNTY3LDU2OCw1NjksNTcwLDU3MSw1NzIsNTczLDU3NCw1NzUsNTc2LDU3Nyw1NzgsNTc5LDU4MCw1ODEsNTgyLDU4Myw1ODQsNTg1LDU4Niw1ODcsNTg4LDU4OSw1OTAsNTkxLDU5Miw1OTMsNTk0LDU5NSw1OTYsNTk3LDU5OCw1OTksNjAwLDYwMSw2MDIsNjAzLDYwNCw2MDUsNjA2LDYwNyw2MDgsNjA5LDYxMCw2MTEsNjEyLDYxMyw2MTQsNjE1LDYxNiw2MTcsNjE4LDYxOSw2MjAsNjIxLDYyMiw2MjMsNjI0LDYyNSw2MjYsNjI3LDYyOCw2MjksNjMwLDYzMSw2MzIsNjMzLDYzNCw2MzUsNjM2LDYzNyw2MzgsNjM5LDY0MCw2NDEsNjQyLDY0Myw2NDQsNjQ1LDY0Niw2NDcsNjQ4LDY0OSw2NTAsNjUxLDY1Miw2NTMsNjU0LDY1NSw2NTYsNjU3LDY1OCw2NTksNjYwLDY2MSw2NjIsNjYzLDY2NCw2NjUsNjY2LDY2Nyw2NjgsNjY5LDY3MCw2NzEsNjcyLDY3Myw2NzQsNjc1LDY3Niw2NzcsNjc4LDY3OSw2ODAsNjgxLDY4Miw2ODMsNjg0LDY4NSw2ODYsNjg3LDY4OCw2ODksNjkwLDY5MSw2OTIsNjkzLDY5NCw2OTUsNjk2LDY5Nyw2OTgsNjk5LDcwMCw3MDEsNzAyLDcwMyw3MDQsNzA1LDcwNiw3MDcsNzA4LDcwOSw3MTAsNzExLDcxMiw3MTMsNzE0LDcxNSw3MTYsNzE3LDcxOCw3MTksNzIwLDcyMSw3MjIsNzIzLDcyNCw3MjUsNzI2LDcyNyw3MjgsNzI5LDczMCw3MzEsNzMyLDczMyw3MzQsNzM1LDczNiw3MzcsNzM4LDczOSw3NDAsNzQxLDc0Miw3NDMsNzQ0LDc0NSw3NDYsNzQ3LDc0OCw3NDksNzUwLDc1MSw3NTIsNzUzLDc1NCw3NTUsNzU2LDc1Nyw3NTgsNzU5LDc2MCw3NjEsNzYyLDc2Myw3NjQsNzY1LDc2Niw3NjcsNzY4LDc2OSw3NzAsNzcxLDc3Miw3NzMsNzc0LDc3NSw3NzYsNzc3LDc3OCw3NzksNzgwLDc4MSw3ODIsNzgzLDc4NCw3ODUsNzg2LDc4Nyw3ODgsNzg5LDc5MCw3OTEsNzkyLDc5Myw3OTQsNzk1LDc5Niw3OTcsNzk4LDc5OSw4MDAsODAxLDgwMiw4MDMsODA0LDgwNSw4MDYsODA3LDgwOCw4MDksODEwLDgxMSw4MTIsODEzLDgxNCw4MTUsODE2LDgxNyw4MTgsODE5LDgyMCw4MjEsODIyLDgyMyw4MjQsODI1LDgyNiw4MjcsODI4LDgyOSw4MzAsODMxLDgzMiw4MzMsODM0LDgzNSw4MzYsODM3LDgzOCw4MzksODQwLDg0MSw4NDIsODQzLDg0NCw4NDUsODQ2LDg0Nyw4NDgsODQ5LDg1MCw4NTEsODUyLDg1Myw4NTQsODU1LDg1Niw4NTcsODU4LDg1OSw4NjAsODYxLDg2Miw4NjMsODY0LDg2NSw4NjYsODY3LDg2OCw4NjksODcwLDg3MSw4NzIsODczLDg3NCw4NzUsODc2LDg3Nyw4NzgsODc5LDg4MCw4ODEsODgyLDg4Myw4ODQsODg1LDg4Niw4ODcsODg4LDg4OSw4OTAsODkxLDg5Miw4OTMsODk0LDg5NSw4OTYsODk3LDg5OCw4OTksOTAwLDkwMSw5MDIsOTAzLDkwNCw5MDUsOTA2LDkwNyw5MDgsOTA5LDkxMCw5MTEsOTEyLDkxMyw5MTQsOTE1LDkxNiw5MTcsOTE4LDkxOSw5MjAsOTIxLDkyMiw5MjMsOTI0LDkyNSw5MjYsOTI3LDkyOCw5MjksOTMwLDkzMSw5MzIsOTMzLDkzNCw5MzUsOTM2LDkzNyw5MzgsOTM5LDk0MCw5NDEsOTQyLDk0Myw5NDQsOTQ1LDk0Niw5NDcsOTQ4LDk0OSw5NTAsOTUxLDk1Miw5NTMsOTU0LDk1NSw5NTYsOTU3LDk1OCw5NTksOTYwLDk2MSw5NjIsOTYzLDk2NCw5NjUsOTY2LDk2Nyw5NjgsOTY5LDk3MCw5NzEsOTcyLDk3Myw5NzQsOTc1LDk3Niw5NzcsOTc4LDk3OSw5ODAsOTgxLDk4Miw5ODMsOTg0LDk4NSw5ODYsOTg3LDk4OCw5ODksOTkwLDk5MSw5OTIsOTkzLDk5NCw5OTUsOTk2LDk5Nyw5OTgsOTk5LDEwMDAsMTAwMSwxMDAyLDEwMDMsMTAwNCwxMDA1LDEwMDYsMTAwNywxMDA4LDEwMDksMTAxMCwxMDExLDEwMTIsMTAxMywxMDE0LDEwMTUsMTAxNiwxMDE3LDEwMTgsMTAxOSwxMDIwLDEwMjEsMTAyMiwxMDIzLDEwMjQsMTAyNSwxMDI2LDEwMjcsMTAyOCwxMDI5LDEwMzAsMTAzMSwxMDMyLDEwMzMsMTAzNCwxMDM1LDEwMzYsMTAzNywxMDM4LDEwMzksMTA0MCwxMDQxLDEwNDIsMTA0MywxMDQ0LDEwNDUsMTA0NiwxMDQ3LDEwNDgsMTA0OSwxMDUwLDEwNTEsMTA1MiwxMDUzLDEwNTQsMTA1NSwxMDU2LDEwNTcsMTA1OCwxMDU5LDEwNjAsMTA2MSwxMDYyLDEwNjMsMTA2NCwxMDY1LDEwNjYsMTA2NywxMDY4LDEwNjksMTA3MCwxMDcxLDEwNzIsMTA3MywxMDc0LDEwNzUsMTA3NiwxMDc3LDEwNzgsMTA3OSwxMDgwLDEwODEsMTA4MiwxMDgzLDEwODQsMTA4NSwxMDg2LDEwODcsMTA4OCwxMDg5LDEwOTAsMTA5MSwxMDkyLDEwOTMsMTA5NCwxMDk1LDEwOTYsMTA5NywxMDk4LDEwOTksMTEwMCwxMTAxLDExMDIsMTEwMywxMTA0LDExMDUsMTEwNiwxMTA3LDExMDgsMTEwOSwxMTEwLDExMTEsMTExMiwxMTEzLDExMTQsMTExNSwxMTE2LDExMTcsMTExOCwxMTE5LDExMjAsMTEyMSwxMTIyLDExMjMsMTEyNCwxMTI1LDExMjYsMTEyNywxMTI4LDExMjksMTEzMCwxMTMxLDExMzIsMTEzMywxMTM0LDExMzUsMTEzNiwxMTM3LDExMzgsMTEzOSwxMTQwLDExNDEsMTE0MiwxMTQzLDExNDQsMTE0NSwxMTQ2LDExNDcsMTE0OCwxMTQ5LDExNTAsMTE1MSwxMTUyLDExNTMsMTE1NCwxMTU1LDExNTYsMTE1NywxMTU4LDExNTksMTE2MCwxMTYxLDExNjIsMTE2MywxMTY0LDExNjUsMTE2NiwxMTY3LDExNjgsMTE2OSwxMTcwLDExNzEsMTE3MiwxMTczLDExNzQsMTE3NSwxMTc2LDExNzcsMTE3OCwxMTc5LDExODAsMTE4MSwxMTgyLDExODMsMTE4NCwxMTg1LDExODYsMTE4NywxMTg4LDExODksMTE5MCwxMTkxLDExOTIsMTE5MywxMTk0LDExOTUsMTE5NiwxMTk3LDExOTgsMTE5OSwxMjAwLDEyMDEsMTIwMiwxMjAzLDEyMDQsMTIwNSwxMjA2LDEyMDcsMTIwOCwxMjA5LDEyMTAsMTIxMSwxMjEyLDEyMTMsMTIxNCwxMjE1LDEyMTYsMTIxNywxMjE4LDEyMTksMTIyMCwxMjIxLDEyMjIsMTIyMywxMjI0LDEyMjUsMTIyNiwxMjI3LDEyMjgsMTIyOSwxMjMwLDEyMzEsMTIzMiwxMjMzLDEyMzQsMTIzNSwxMjM2LDEyMzcsMTIzOCwxMjM5LDEyNDAsMTI0MSwxMjQyLDEyNDMsMTI0NCwxMjQ1LDEyNDYsMTI0NywxMjQ4LDEyNDksMTI1MCwxMjUxLDEyNTIsMTI1MywxMjU0LDEyNTUsMTI1NiwxMjU3LDEyNTgsMTI1OSwxMjYwLDEyNjEsMTI2MiwxMjYzLDEyNjQsMTI2NSwxMjY2LDEyNjcsMTI2OCwxMjY5LDEyNzAsMTI3MSwxMjcyLDEyNzMsMTI3NCwxMjc1LDEyNzYsMTI3NywxMjc4LDEyNzksMTI4MCwxMjgxLDEyODIsMTI4MywxMjg0LDEyODUsMTI4NiwxMjg3LDEyODgsMTI4OSwxMjkwLDEyOTEsMTI5MiwxMjkzLDEyOTQsMTI5NSwxMjk2LDEyOTcsMTI5OCwxMjk5LDEzMDAsMTMwMSwxMzAyLDEzMDMsMTMwNCwxMzA1LDEzMDYsMTMwNywxMzA4LDEzMDksMTMxMCwxMzExLDEzMTIsMTMxMywxMzE0LDEzMTUsMTMxNiwxMzE3LDEzMTgsMTMxOSwxMzIwLDEzMjEsMTMyMiwxMzIzLDEzMjQsMTMyNSwxMzI2LDEzMjcsMTMyOCwxMzI5LDEzMzAsMTMzMSwxMzMyLDEzMzMsMTMzNCwxMzM1LDEzMzYsMTMzNywxMzM4LDEzMzksMTM0MCwxMzQxLDEzNDIsMTM0MywxMzQ0LDEzNDUsMTM0NiwxMzQ3LDEzNDgsMTM0OSwxMzUwLDEzNTEsMTM1MiwxMzUzLDEzNTQsMTM1NSwxMzU2LDEzNTcsMTM1OCwxMzU5LDEzNjAsMTM2MSwxMzYyLDEzNjMsMTM2NCwxMzY1LDEzNjYsMTM2NywxMzY4LDEzNjksMTM3MCwxMzcxLDEzNzIsMTM3MywxMzc0LDEzNzUsMTM3NiwxMzc3LDEzNzgsMTM3OSwxMzgwLDEzODEsMTM4MiwxMzgzLDEzODQsMTM4NSwxMzg2LDEzODcsMTM4OCwxMzg5LDEzOTAsMTM5MSwxMzkyLDEzOTMsMTM5NCwxMzk1LDEzOTYsMTM5NywxMzk4LDEzOTksMTQwMCwxNDAxLDE0MDIsMTQwMywxNDA0LDE0MDUsMTQwNiwxNDA3LDE0MDgsMTQwOSwxNDEwLDE0MTEsMTQxMiwxNDEzLDE0MTQsMTQxNSwxNDE2LDE0MTcsMTQxOCwxNDE5LDE0MjAsMTQyMSwxNDIyLDE0MjMsMTQyNCwxNDI1LDE0MjYsMTQyNywxNDI4LDE0MjksMTQzMCwxNDMxLDE0MzIsMTQzMywxNDM0LDE0MzUsMTQzNiwxNDM3LDE0MzgsMTQzOSwxNDQwLDE0NDEsMTQ0MiwxNDQzLDE0NDQsMTQ0NSwxNDQ2LDE0NDcsMTQ0OCwxNDQ5LDE0NTAsMTQ1MSwxNDUyLDE0NTMsMTQ1NCwxNDU1LDE0NTYsMTQ1NywxNDU4LDE0NTksMTQ2MCwxNDYxLDE0NjIsMTQ2MywxNDY0LDE0NjUsMTQ2NiwxNDY3LDE0NjgsMTQ2OSwxNDcwLDE0NzEsMTQ3MiwxNDczLDE0NzQsMTQ3NSwxNDc2LDE0NzcsMTQ3OCwxNDc5LDE0ODAsMTQ4MSwxNDgyLDE0ODMsMTQ4NCwxNDg1LDE0ODYsMTQ4NywxNDg4LDE0ODksMTQ5MCwxNDkxLDE0OTIsMTQ5MywxNDk0LDE0OTUsMTQ5NiwxNDk3LDE0OTgsMTQ5OSwxNTAwLDE1MDEsMTUwMiwxNTAzLDE1MDQsMTUwNSwxNTA2LDE1MDcsMTUwOCwxNTA5LDE1MTAsMTUxMSwxNTEyLDE1MTMsMTUxNCwxNTE1LDE1MTYsMTUxNywxNTE4LDE1MTksMTUyMCwxNTIxLDE1MjIsMTUyMywxNTI0LDE1MjUsMTUyNiwxNTI3LDE1MjgsMTUyOSwxNTMwLDE1MzEsMTUzMiwxNTMzLDE1MzQsMTUzNSwxNTM2LDE1MzcsMTUzOCwxNTM5LDE1NDAsMTU0MSwxNTQyLDE1NDMsMTU0NCwxNTQ1LDE1NDYsMTU0NywxNTQ4LDE1NDksMTU1MCwxNTUxLDE1NTIsMTU1MywxNTU0LDE1NTUsMTU1NiwxNTU3LDE1NTgsMTU1OSwxNTYwLDE1NjEsMTU2MiwxNTYzLDE1NjQsMTU2NSwxNTY2LDE1NjcsMTU2OCwxNTY5LDE1NzAsMTU3MSwxNTcyLDE1NzMsMTU3NCwxNTc1LDE1NzYsMTU3NywxNTc4LDE1NzksMTU4MCwxNTgxLDE1ODIsMTU4MywxNTg0LDE1ODUsMTU4NiwxNTg3LDE1ODgsMTU4OSwxNTkwLDE1OTEsMTU5MiwxNTkzLDE1OTQsMTU5NSwxNTk2LDE1OTcsMTU5OCwxNTk5LDE2MDAsMTYwMSwxNjAyLDE2MDMsMTYwNCwxNjA1LDE2MDYsMTYwNywxNjA4LDE2MDksMTYxMCwxNjExLDE2MTIsMTYxMywxNjE0LDE2MTUsMTYxNiwxNjE3LDE2MTgsMTYxOSwxNjIwLDE2MjEsMTYyMiwxNjIzLDE2MjQsMTYyNSwxNjI2LDE2MjcsMTYyOCwxNjI5LDE2MzAsMTYzMSwxNjMyLDE2MzMsMTYzNCwxNjM1LDE2MzYsMTYzNywxNjM4LDE2MzksMTY0MCwxNjQxLDE2NDIsMTY0MywxNjQ0LDE2NDUsMTY0NiwxNjQ3LDE2NDgsMTY0OSwxNjUwLDE2NTEsMTY1MiwxNjUzLDE2NTQsMTY1NSwxNjU2LDE2NTcsMTY1OCwxNjU5LDE2NjAsMTY2MSwxNjYyLDE2NjMsMTY2NCwxNjY1LDE2NjYsMTY2NywxNjY4LDE2NjksMTY3MCwxNjcxLDE2NzIsMTY3MywxNjc0LDE2NzUsMTY3NiwxNjc3LDE2NzgsMTY3OSwxNjgwLDE2ODEsMTY4MiwxNjgzLDE2ODQsMTY4NSwxNjg2LDE2ODcsMTY4OCwxNjg5LDE2OTAsMTY5MSwxNjkyLDE2OTMsMTY5NCwxNjk1LDE2OTYsMTY5NywxNjk4LDE2OTksMTcwMCwxNzAxLDE3MDIsMTcwMywxNzA0LDE3MDUsMTcwNiwxNzA3LDE3MDgsMTcwOSwxNzEwLDE3MTEsMTcxMiwxNzEzLDE3MTQsMTcxNSwxNzE2LDE3MTcsMTcxOCwxNzE5LDE3MjAsMTcyMSwxNzIyLDE3MjMsMTcyNCwxNzI1LDE3MjYsMTcyNywxNzI4LDE3MjksMTczMCwxNzMxLDE3MzIsMTczMywxNzM0LDE3MzUsMTczNiwxNzM3LDE3MzgsMTczOSwxNzQwLDE3NDEsMTc0MiwxNzQzLDE3NDQsMTc0NSwxNzQ2LDE3NDcsMTc0OCwxNzQ5LDE3NTAsMTc1MSwxNzUyLDE3NTMsMTc1NCwxNzU1LDE3NTYsMTc1NywxNzU4LDE3NTksMTc2MCwxNzYxLDE3NjIsMTc2MywxNzY0LDE3NjUsMTc2NiwxNzY3LDE3NjgsMTc2OSwxNzcwLDE3NzEsMTc3MiwxNzczLDE3NzQsMTc3NSwxNzc2LDE3NzcsMTc3OCwxNzc5LDE3ODAsMTc4MSwxNzgyLDE3ODMsMTc4NCwxNzg1LDE3ODYsMTc4NywxNzg4LDE3ODksMTc5MCwxNzkxLDE3OTIsMTc5MywxNzk0LDE3OTUsMTc5NiwxNzk3LDE3OTgsMTc5OSwxODAwLDE4MDEsMTgwMiwxODAzLDE4MDQsMTgwNSwxODA2LDE4MDcsMTgwOCwxODA5LDE4MTAsMTgxMSwxODEyLDE4MTMsMTgxNCwxODE1LDE4MTYsMTgxNywxODE4LDE4MTksMTgyMCwxODIxLDE4MjIsMTgyMywxODI0LDE4MjUsMTgyNiwxODI3LDE4MjgsMTgyOSwxODMwLDE4MzEsMTgzMiwxODMzLDE4MzQsMTgzNSwxODM2LDE4MzcsMTgzOCwxODM5LDE4NDAsMTg0MSwxODQyLDE4NDMsMTg0NCwxODQ1LDE4NDYsMTg0NywxODQ4LDE4NDksMTg1MCwxODUxLDE4NTIsMTg1MywxODU0LDE4NTUsMTg1NiwxODU3LDE4NTgsMTg1OSwxODYwLDE4NjEsMTg2MiwxODYzLDE4NjQsMTg2NSwxODY2LDE4NjcsMTg2OCwxODY5LDE4NzAsMTg3MSwxODcyLDE4NzMsMTg3NCwxODc1LDE4NzYsMTg3NywxODc4LDE4NzksMTg4MCwxODgxLDE4ODIsMTg4MywxODg0LDE4ODUsMTg4NiwxODg3LDE4ODgsMTg4OSwxODkwLDE4OTEsMTg5MiwxODkzLDE4OTQsMTg5NSwxODk2LDE4OTcsMTg5OCwxODk5LDE5MDAsMTkwMSwxOTAyLDE5MDMsMTkwNCwxOTA1LDE5MDYsMTkwNywxOTA4LDE5MDksMTkxMCwxOTExLDE5MTIsMTkxMywxOTE0LDE5MTUsMTkxNiwxOTE3LDE5MTgsMTkxOSwxOTIwLDE5MjEsMTkyMiwxOTIzLDE5MjQsMTkyNSwxOTI2LDE5MjcsMTkyOCwxOTI5LDE5MzAsMTkzMSwxOTMyLDE5MzMsMTkzNCwxOTM1LDE5MzYsMTkzNywxOTM4LDE5MzksMTk0MCwxOTQxLDE5NDIsMTk0MywxOTQ0LDE5NDUsMTk0NiwxOTQ3LDE5NDgsMTk0OSwxOTUwLDE5NTEsMTk1MiwxOTUzLDE5NTQsMTk1NSwxOTU2LDE5NTcsMTk1OCwxOTU5LDE5NjAsMTk2MSwxOTYyLDE5NjMsMTk2NCwxOTY1LDE5NjYsMTk2NywxOTY4LDE5NjksMTk3MCwxOTcxLDE5NzIsMTk3MywxOTc0LDE5NzUsMTk3NiwxOTc3LDE5NzgsMTk3OSwxOTgwLDE5ODEsMTk4MiwxOTgzLDE5ODQsMTk4NSwxOTg2LDE5ODcsMTk4OCwxOTg5LDE5OTAsMTk5MSwxOTkyLDE5OTMsMTk5NCwxOTk1LDE5OTYsMTk5NywxOTk4LDE5OTksMjAwMF0='));

// Typical User object
JSON.parse(atob('eyJpZCI6MSwiZ2l2ZW5fbmFtZSI6IlRlc3QiLCJmYW1pbHlfbmFtZSI6IlVzZXIiLCJzdWZmaXgiOm51bGwsImRpc3BsYXlfbmFtZSI6IlN5c3RlbSIsImxlZ2FsX25hbWUiOiJTeXN0ZW0iLCJ1c2VybmFtZSI6InRlc3QiLCJyb2xlIjoiZ3Vlc3QiLCJlbWFpbCI6InRlc3RAdGVzdC5jb20iLCJlbWFpbDIiOm51bGwsInBob3RvIjpudWxsLCJhdmF0YXJfdXBsb2FkX2lkIjpudWxsLCJsb2NhbGUiOiJlbiIsInRpbWV6b25lIjoiQW1lcmljYVwvTmV3X1lvcmsiLCJsYXRpdHVkZSI6bnVsbCwibG9uZ2l0dWRlIjpudWxsLCJjb25maXJtZWQiOnRydWUsImNyZWF0ZWRfYXQiOiIxOTk3LTAxLTAxIDAwOjAwOjAwIiwidXBkYXRlZF9hdCI6IjE5OTctMDEtMDEgMDA6MDA6MDAiLCJhY2NvdW50X2lkIjoxLCJwdWJsaWNfaWQiOm51bGwsImFnZ3JlZ2F0ZV9yb2xlIjoiZ3Vlc3QifQ=='));

@inxilpro
Copy link
Contributor

inxilpro commented Nov 3, 2021

A couple other notes:

  • The JsString implementation takes the Jsonable and Arrayable interfaces into account
  • It enforces the JSON_HEX_TAG, JSON_HEX_APOS, JSON_HEX_AMP, and JSON_HEX_QUOT flags and always uses single quotes for the final result to ensure that you don't get bitten by single/double quote issues (and help mitigate XSS concerns)

@taylorotwell taylorotwell merged commit f429789 into laravel:8.x Nov 3, 2021
@taylorotwell
Copy link
Member

Thanks for contributing to Laravel! ❤️

LukeTowers added a commit to wintercms/winter that referenced this pull request Feb 14, 2022
Laravel 8.x added a JS helper to turn PHP data into JS data (see laravel/framework#39389) however I'm not convinced of it's utility over json_encode so this is commented out by default for now.
LukeTowers added a commit to wintercms/wn-system-module that referenced this pull request Feb 15, 2022
Laravel 8.x added a JS helper to turn PHP data into JS data (see laravel/framework#39389) however I'm not convinced of it's utility over json_encode so this is commented out by default for now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants