14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_json.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/base/json_parser.h" 194514f5e3Sopenharmony_ci#include "ecmascript/base/json_stringifier.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 224514f5e3Sopenharmony_cinamespace { 234514f5e3Sopenharmony_ciusing TransformType = base::JsonHelper::TransformType; 244514f5e3Sopenharmony_ciusing ParseOptions = base::JsonHelper::ParseOptions; 254514f5e3Sopenharmony_ciusing ParseReturnType = base::JsonHelper::ParseReturnType; 264514f5e3Sopenharmony_ciusing BigIntMode = base::JsonHelper::BigIntMode; 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_civoid InitWithTransformType(JSHandle<GlobalEnv> &env, TransformType transformType, 294514f5e3Sopenharmony_ci JSMutableHandle<JSFunction> &constructor, SCheckMode &sCheckMode) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci if (transformType == TransformType::NORMAL || transformType == TransformType::BIGINT) { 324514f5e3Sopenharmony_ci sCheckMode = SCheckMode::CHECK; 334514f5e3Sopenharmony_ci constructor.Update(env->GetObjectFunction()); 344514f5e3Sopenharmony_ci } else { 354514f5e3Sopenharmony_ci sCheckMode = SCheckMode::SKIP; 364514f5e3Sopenharmony_ci constructor.Update(env->GetSObjectFunction()); 374514f5e3Sopenharmony_ci } 384514f5e3Sopenharmony_ci} 394514f5e3Sopenharmony_ci} // namespace 404514f5e3Sopenharmony_ci 414514f5e3Sopenharmony_ciusing Internalize = base::Internalize; 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_ciJSTaggedValue BuiltinsJson::Parse(EcmaRuntimeCallInfo *argv) 444514f5e3Sopenharmony_ci{ 454514f5e3Sopenharmony_ci return ParseWithTransformType(argv, TransformType::NORMAL); 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSendableJson::Parse(EcmaRuntimeCallInfo *argv) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci uint32_t argc = argv->GetArgsNumber(); 514514f5e3Sopenharmony_ci if (argc >= 2) { // 2: two args 524514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> reviverVal = GetCallArg(argv, 1); 534514f5e3Sopenharmony_ci if (!reviverVal->IsUndefined()) { 544514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), GET_MESSAGE_STRING(ReviverOnlySupportUndefined), 554514f5e3Sopenharmony_ci JSTaggedValue::Exception()); 564514f5e3Sopenharmony_ci } 574514f5e3Sopenharmony_ci } 584514f5e3Sopenharmony_ci return BuiltinsJson::ParseWithTransformType(argv, TransformType::SENDABLE); 594514f5e3Sopenharmony_ci} 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ciJSTaggedValue BuiltinsBigIntJson::Parse(EcmaRuntimeCallInfo *argv) 624514f5e3Sopenharmony_ci{ 634514f5e3Sopenharmony_ci return BuiltinsJson::ParseWithTransformType(argv, TransformType::BIGINT); 644514f5e3Sopenharmony_ci} 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci// 24.5.1 674514f5e3Sopenharmony_ciJSTaggedValue BuiltinsJson::ParseWithTransformType(EcmaRuntimeCallInfo *argv, TransformType transformType) 684514f5e3Sopenharmony_ci{ 694514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Json, Parse); 704514f5e3Sopenharmony_ci ASSERT(argv); 714514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 724514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_ci uint32_t argc = argv->GetArgsNumber(); 774514f5e3Sopenharmony_ci if (argc == 0) { 784514f5e3Sopenharmony_ci JSHandle<JSObject> syntaxError = factory->GetJSError(base::ErrorType::SYNTAX_ERROR, 794514f5e3Sopenharmony_ci "arg is empty", StackCheck::NO); 804514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, syntaxError.GetTaggedValue(), JSTaggedValue::Exception()); 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci 834514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 844514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> reviverVal(thread, JSTaggedValue::Undefined()); 854514f5e3Sopenharmony_ci ParseOptions parseOptions; 864514f5e3Sopenharmony_ci if (argc == 2) { // 2: two args 874514f5e3Sopenharmony_ci reviverVal.Update(GetCallArg(argv, 1)); 884514f5e3Sopenharmony_ci } else if (argc == 3 && base::JsonHelper::IsTypeSupportBigInt(transformType)) { // 3: three args 894514f5e3Sopenharmony_ci reviverVal.Update(GetCallArg(argv, 1)); 904514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> options = GetCallArg(argv, 2); // 2: two args 914514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> modeKey(factory->NewFromStdString("bigIntMode")); 924514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typeKey(factory->NewFromStdString("parseReturnType")); 934514f5e3Sopenharmony_ci if (options->IsECMAObject()) { 944514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> type = JSTaggedValue::GetProperty(thread, options, typeKey).GetValue(); 954514f5e3Sopenharmony_ci if (transformType == TransformType::SENDABLE && type->IsInt() && type->GetInt() == 1) { // 1: map 964514f5e3Sopenharmony_ci parseOptions.returnType = ParseReturnType::MAP; 974514f5e3Sopenharmony_ci } 984514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> modeValue = JSTaggedValue::GetProperty(thread, options, modeKey).GetValue(); 994514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1004514f5e3Sopenharmony_ci if (modeValue->IsInt()) { 1014514f5e3Sopenharmony_ci int val = modeValue->GetInt(); 1024514f5e3Sopenharmony_ci if (val == 2) { // 2: bigIntMode 1034514f5e3Sopenharmony_ci parseOptions.bigIntMode = BigIntMode::ALWAYS_PARSE_AS_BIGINT; 1044514f5e3Sopenharmony_ci } else if (val == 1) { 1054514f5e3Sopenharmony_ci parseOptions.bigIntMode = BigIntMode::PARSE_AS_BIGINT; 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci } 1104514f5e3Sopenharmony_ci return ParseWithTransformType(thread->GetEcmaVM(), msg, reviverVal, transformType, parseOptions); 1114514f5e3Sopenharmony_ci} 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ciJSTaggedValue BuiltinsJson::ParseWithTransformType(const EcmaVM *vm, JSHandle<JSTaggedValue> &msg, 1144514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> &reviverVal, TransformType transformType, 1154514f5e3Sopenharmony_ci ParseOptions options) 1164514f5e3Sopenharmony_ci{ 1174514f5e3Sopenharmony_ci JSThread *thread = vm->GetJSThread(); 1184514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1194514f5e3Sopenharmony_ci 1204514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1214514f5e3Sopenharmony_ci JSHandle<EcmaString> parseString = JSTaggedValue::ToString(thread, msg); 1224514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1234514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> result; 1244514f5e3Sopenharmony_ci if (EcmaStringAccessor(parseString).IsUtf8()) { 1254514f5e3Sopenharmony_ci panda::ecmascript::base::Utf8JsonParser parser(thread, transformType, options); 1264514f5e3Sopenharmony_ci result = parser.Parse(parseString); 1274514f5e3Sopenharmony_ci } else { 1284514f5e3Sopenharmony_ci panda::ecmascript::base::Utf16JsonParser parser(thread, transformType, options); 1294514f5e3Sopenharmony_ci result = parser.Parse(*parseString); 1304514f5e3Sopenharmony_ci } 1314514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1324514f5e3Sopenharmony_ci JSTaggedValue reviver = JSTaggedValue::Undefined(); 1334514f5e3Sopenharmony_ci if (reviverVal->IsJSFunction()) { 1344514f5e3Sopenharmony_ci reviver = reviverVal.GetTaggedValue(); 1354514f5e3Sopenharmony_ci if (reviver.IsCallable()) { 1364514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> callbackfnHandle(thread, reviver); 1374514f5e3Sopenharmony_ci // Let root be ! OrdinaryObjectCreate(%Object.prototype%). 1384514f5e3Sopenharmony_ci JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 1394514f5e3Sopenharmony_ci JSMutableHandle<JSFunction> constructor(thread, JSTaggedValue::Undefined()); 1404514f5e3Sopenharmony_ci SCheckMode sCheckMode = SCheckMode::CHECK; 1414514f5e3Sopenharmony_ci InitWithTransformType(env, transformType, constructor, sCheckMode); 1424514f5e3Sopenharmony_ci JSHandle<JSObject> root = factory->NewJSObjectByConstructor(constructor); 1434514f5e3Sopenharmony_ci // Let rootName be the empty String. 1444514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> rootName(factory->GetEmptyString()); 1454514f5e3Sopenharmony_ci // Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered). 1464514f5e3Sopenharmony_ci bool success = JSObject::CreateDataProperty(thread, root, rootName, result, sCheckMode); 1474514f5e3Sopenharmony_ci if (success) { 1484514f5e3Sopenharmony_ci result = Internalize::InternalizeJsonProperty(thread, root, rootName, callbackfnHandle, transformType); 1494514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci if (transformType == TransformType::SENDABLE) { 1544514f5e3Sopenharmony_ci if (result->IsHeapObject() && !result->IsJSShared() && !result->IsString()) { 1554514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(ClassNotDerivedFromShared), 1564514f5e3Sopenharmony_ci JSTaggedValue::Exception()); 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci return result.GetTaggedValue(); 1604514f5e3Sopenharmony_ci} 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ci// 24.5.2 1634514f5e3Sopenharmony_ciJSTaggedValue BuiltinsJson::Stringify(EcmaRuntimeCallInfo *argv) 1644514f5e3Sopenharmony_ci{ 1654514f5e3Sopenharmony_ci return BuiltinsJson::StringifyWithTransformType(argv, TransformType::NORMAL); 1664514f5e3Sopenharmony_ci} 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSendableJson::Stringify(EcmaRuntimeCallInfo *argv) 1694514f5e3Sopenharmony_ci{ 1704514f5e3Sopenharmony_ci return BuiltinsJson::StringifyWithTransformType(argv, TransformType::SENDABLE); 1714514f5e3Sopenharmony_ci} 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ciJSTaggedValue BuiltinsBigIntJson::Stringify(EcmaRuntimeCallInfo *argv) 1744514f5e3Sopenharmony_ci{ 1754514f5e3Sopenharmony_ci return BuiltinsJson::StringifyWithTransformType(argv, TransformType::BIGINT); 1764514f5e3Sopenharmony_ci} 1774514f5e3Sopenharmony_ci 1784514f5e3Sopenharmony_ciJSTaggedValue BuiltinsJson::StringifyWithTransformType(EcmaRuntimeCallInfo *argv, TransformType transformType) 1794514f5e3Sopenharmony_ci{ 1804514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Json, Stringify); 1814514f5e3Sopenharmony_ci ASSERT(argv); 1824514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1834514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ci uint32_t argc = argv->GetArgsNumber(); 1864514f5e3Sopenharmony_ci JSTaggedValue value = GetCallArg(argv, 0).GetTaggedValue(); 1874514f5e3Sopenharmony_ci JSTaggedValue replacer = JSTaggedValue::Undefined(); 1884514f5e3Sopenharmony_ci JSTaggedValue gap = JSTaggedValue::Undefined(); 1894514f5e3Sopenharmony_ci 1904514f5e3Sopenharmony_ci if (argc == 2) { // 2: 2 args 1914514f5e3Sopenharmony_ci replacer = GetCallArg(argv, 1).GetTaggedValue(); 1924514f5e3Sopenharmony_ci } else if (argc == 3) { // 3: 3 args 1934514f5e3Sopenharmony_ci replacer = GetCallArg(argv, 1).GetTaggedValue(); 1944514f5e3Sopenharmony_ci gap = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD).GetTaggedValue(); 1954514f5e3Sopenharmony_ci } 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> handleValue(thread, value); 1984514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> handleReplacer(thread, replacer); 1994514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> handleGap(thread, gap); 2004514f5e3Sopenharmony_ci panda::ecmascript::base::JsonStringifier stringifier(thread, transformType); 2014514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> result = stringifier.Stringify(handleValue, handleReplacer, handleGap); 2024514f5e3Sopenharmony_ci 2034514f5e3Sopenharmony_ci return result.GetTaggedValue(); 2044514f5e3Sopenharmony_ci} 2054514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins 206