From 4e682003172af4e0913e5b71130da6effd5c814c Mon Sep 17 00:00:00 2001 From: lijincheng Date: Thu, 31 Jul 2025 02:52:50 +0800 Subject: [PATCH] Hide some APIs in standard library 1.137 APIs distributed in 37 files that introducd by ArkTS 1.2 are hidden. Issue:https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICPXN0 Signed-off-by: lijincheng --- static_core/plugins/ets/stdlib/BUILD.gn | 2 +- .../plugins/ets/stdlib/package_stdlib.py | 140 +++++++++++ .../plugins/ets/stdlib/package_stdlib.sh | 31 --- .../plugins/ets/stdlib/std/hiddable_APIs.json | 222 ++++++++++++++++++ 4 files changed, 363 insertions(+), 32 deletions(-) create mode 100755 static_core/plugins/ets/stdlib/package_stdlib.py delete mode 100755 static_core/plugins/ets/stdlib/package_stdlib.sh create mode 100644 static_core/plugins/ets/stdlib/std/hiddable_APIs.json diff --git a/static_core/plugins/ets/stdlib/BUILD.gn b/static_core/plugins/ets/stdlib/BUILD.gn index 757b921b76..0433c59887 100644 --- a/static_core/plugins/ets/stdlib/BUILD.gn +++ b/static_core/plugins/ets/stdlib/BUILD.gn @@ -22,7 +22,7 @@ if (ark_standalone_build) { } action("copy_stdlib") { - script = "package_stdlib.sh" + script = "package_stdlib.py" args = [ rebase_path("std"), rebase_path("escompat"), diff --git a/static_core/plugins/ets/stdlib/package_stdlib.py b/static_core/plugins/ets/stdlib/package_stdlib.py new file mode 100755 index 0000000000..a52090cb5a --- /dev/null +++ b/static_core/plugins/ets/stdlib/package_stdlib.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2024-2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import stat +import sys +import shutil +import json +import re +from pathlib import Path + + +def load_json_file(file_path: Path) -> dict: + """Load JSON file; return parsed data""" + try: + with os.fdopen(os.open(file_path, os.O_RDONLY, stat.S_IRUSR), 'r', encoding='utf-8') as f: + return json.load(f) + except json.JSONDecodeError as e: + print(f"Error: Hiddable Interface file format is invalid in ({file_path}): {e}") + return {} + + +def read_hidden_interfaces(std_dir: Path) -> dict: + json_files = [ + "hiddable_APIs.json" + ] + hidden_interfaces = {} + for json_file in json_files: + hidden_interfaces_file = std_dir / json_file + + if not hidden_interfaces_file.exists(): + print("Error: Hiddable Interface file not found. Will Copy All files.") + return hidden_interfaces + + data = load_json_file(hidden_interfaces_file) + for item in data: + file = item.get('file') + interfaces = item.get('interfaces', []) + if file: + hidden_interfaces[file] = set(interfaces) + + return hidden_interfaces + + +def process_file_with_hidden_interfaces( + source_file: Path, + target_file: Path, + hidden_ifaces: set, + interface_pattern: re.Pattern) -> None: + """Replace export keyword with empty string if interface is hiddable""" + with os.fdopen(os.open(source_file, os.O_RDONLY, stat.S_IRUSR), 'r', encoding='utf-8') as f: + lines = f.readlines() + + modified_lines = [] + + for line in lines: + match = interface_pattern.search(line) + if match: + interface_type, interface_name = match.groups() + if interface_name in hidden_ifaces: + modified_line = re.sub(r'\bexport \b', '', line) + modified_lines.append(modified_line) + continue + + modified_lines.append(line) + + with os.fdopen( + os.open(target_file, os.O_RDWR | os.O_CREAT | os.O_TRUNC, stat.S_IWUSR | stat.S_IRUSR), 'w') as fout: + fout.writelines(modified_lines) + + +def copy_files_with_filter(std_dir: Path, target_dir: Path, hidden_interfaces: dict) -> None: + """Copy stdlib files; filter interfaces by hiddable_APIs.json""" + copied_count = 0 + skipped_count = 0 + filtered_files = 0 + + interface_pattern = re.compile( + r'^\s*export\s+(?:final\s+|abstract\s+)?(class|interface|@interface|function)\s+(\w+)' + ) + + for root, _, files in os.walk(std_dir): + rel_path = Path(root).relative_to(std_dir) + target_subdir = target_dir / 'std' / rel_path + + target_subdir.mkdir(parents=True, exist_ok=True) + + for file in files: + source_file = Path(root) / file + rel_file_path = rel_path / file + rel_file_str = str(rel_file_path) + + if rel_file_str not in hidden_interfaces: + shutil.copy2(source_file, target_subdir) + copied_count += 1 + continue + + hidden_ifaces = hidden_interfaces[rel_file_str] + + if not hidden_ifaces: + skipped_count += 1 + continue + filtered_files += 1 + target_file = target_subdir / file + process_file_with_hidden_interfaces(source_file, target_file, hidden_ifaces, interface_pattern) + copied_count += 1 + + +def main(): + if len(sys.argv) != 4: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + + std_dir = Path(sys.argv[1]) + escompact_dir = Path(sys.argv[2]) + target_dir = Path(sys.argv[3]) + + target_dir.mkdir(parents=True, exist_ok=True) + hidden_interfaces = read_hidden_interfaces(std_dir) + copy_files_with_filter(std_dir, target_dir, hidden_interfaces) + + escompat_target = target_dir / escompact_dir.name + shutil.copytree(escompact_dir, escompat_target, dirs_exist_ok=True) + + +if __name__ == "__main__": + main() diff --git a/static_core/plugins/ets/stdlib/package_stdlib.sh b/static_core/plugins/ets/stdlib/package_stdlib.sh deleted file mode 100755 index cbd4dc2985..0000000000 --- a/static_core/plugins/ets/stdlib/package_stdlib.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2025 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -eo pipefail - -if [ $# -ne 3 ]; then - echo "Usage: $0 " - exit 1 -fi - -STD="$1" -ESCOMPACT="$2" -TARGET="$3" - -if [ ! -d "$TARGET" ]; then - mkdir -p "$TARGET" -fi - -cp -r -f "$STD" "$TARGET" -cp -r -f "$ESCOMPACT" "$TARGET" diff --git a/static_core/plugins/ets/stdlib/std/hiddable_APIs.json b/static_core/plugins/ets/stdlib/std/hiddable_APIs.json new file mode 100644 index 0000000000..1807387d4a --- /dev/null +++ b/static_core/plugins/ets/stdlib/std/hiddable_APIs.json @@ -0,0 +1,222 @@ +[ + { + "file": "debug/RuntimeDebug.ets", + "interfaces": [ + "RuntimeDebug" + ] + }, + { + "file": "debug/Logger.ets", + "interfaces": [ + "Logger" + ] + }, + { + "file": "core/EnumConstant.ets", + "interfaces": [ + "EnumConstant" + ] + }, + { + "file": "core/Void.ets", + "interfaces": [ + "Void" + ] + }, + { + "file": "core/RuntimeLinkerErrors.ets", + "interfaces": [ + "LinkerVerificationError", + "LinkerUnresolvedClassError", + "LinkerUnresolvedFieldError", + "LinkerUnresolvedMethodError", + "LinkerBadSupertypeError", + "LinkerTypeCircularityError", + "LinkerMethodConflictError", + "LinkerAbstractMethodError", + "LinkerClassNotFoundError" + ] + }, + { + "file": "core/LocaleMatch.ets", + "interfaces": [ + "intlLookUpLocale", + "intlBestFitLocale", + "intlLookUpLocales", + "intlBestFitLocales", + "intlLocalesToLanguageTags" + ] + }, + { + "file": "core/Errors.ets", + "interfaces": [ + "JSONTypeError", + "CoroutinesLimitExceedError", + "InvalidCoroutineOperationError" + ] + }, + { + "file": "core/Value.ets", + "interfaces": [ + "LambdaValue", + "BooleanValue", + "ByteValue", + "ShortValue", + "CharValue", + "IntValue", + "FloatValue", + "DoubleValue", + "LongValue", + "StringValue", + "NullValue", + "UndefinedValue", + "VoidValue" + ] + }, + { + "file": "core/Runtime.ets", + "interfaces": [ + "__runtimeEquals", + "__runtimeSameValueZero", + "__runtimeSameValue", + "__runtimeIsSameReference" + ] + }, + { + "file": "core/DisplayNames.ets", + "interfaces": [ + "DisplayNamesLocaleMatcherOptions", + "DisplayNames" + ] + }, + { + "file": "core/Numeric.ets", + "interfaces": [ + "Floating" + ] + }, + { + "file": "core/Exceptions.ets", + "interfaces": [ + "NoDataException", + "ArgumentOutOfRangeException", + "IllegalStateException", + "UnsupportedOperationException", + "IllegalArgumentException", + "RuntimeException" + ] + }, + { + "file": "core/System.ets", + "interfaces": [ + "stackTraceLines" + ] + }, + { + "file": "core/TypeCreator.ets", + "interfaces": [ + "TypeAPICreateError", + "TypeCreator", + "ClassTypeCreator", + "InterfaceTypeCreator", + "LambdaTypeCreator", + "FieldCreator", + "ParameterCreator", + "MethodCreator", + "CallableBody", + "CallableBodyDefault", + "CallableBodyMethod", + "CallableBodyFunction", + "CallableBodyErasedFunction" + ] + }, + { + "file": "core/Parameter.ets", + "interfaces": [ + "Parameter" + ] + }, + { + "file": "core/AbcFile.ets", + "interfaces": [ + "AbcFileNotFoundError" + ] + }, + { + "file": "core/UnionCase.ets", + "interfaces": [ + "UnionCase" + ] + }, + { + "file": "core/Json.ets", + "interfaces": [ + "JsonTypeError" + ] + }, + { + "file": "containers/ListInt.ets", + "interfaces": [ + "ListInt" + ] + }, + { + "file": "containers/ListString.ets", + "interfaces": [ + "ListString" + ] + }, + { + "file": "containers/AVLTree.ets", + "interfaces": [ + "newEmpty", + "isEmpty", + "isLeaf", + "isNode", + "height", + "newNode", + "newLeaf", + "addToTree", + "mergeTree", + "removeFromTree", + "lookupTree", + "count" + ] + }, + { + "file": "containers/UndefinableStringArray.ets", + "interfaces": [ + "UndefinableStringArray" + ] + }, + { + "file": "containers/ListObject.ets", + "interfaces": [ + "ListObject" + ] + }, + { + "file": "containers/UndefinableObjectArray.ets", + "interfaces": [ + "UndefinableObjectArray" + ] + }, + { + "file": "containers/ArrayAsListObject.ets", + "interfaces": [ + "ArrayAsListObject" + ] + }, + { + "file": "containers/ArrayAsListString.ets", + "interfaces": [ + "ArrayAsListString" + ] + }, + { + "file": "containers/ArrayAsListInt.ets", + "interfaces": [ + "ArrayAsListInt" + ] + } +] \ No newline at end of file -- Gitee