1# Copyright (c) 2023-2025 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14add_custom_target(declgen_ets2ts_test) 15add_custom_target(declgen_ets2ts_test_diff) 16add_dependencies(ets_interop_js_tests declgen_ets2ts_test_diff declgen_ets2ts_test) 17 18# Create create_declgen_ets2ts_test test 19# 20# Declgen test consists of files: 21# ${ROOT_DIR}/*.ets 22# ${ROOT_DIR}/*.ts 23# ${ROOT_DIR}/*.js 24# ${ROOT_DIR}/*.expected 25# This function: 26# 1. Compiles 'ets' files with es2panda into 'abc' and decl 'ts': 27# ${ROOT_DIR}/*.ets -> ${BINARY_ROOT_DIR}/*.abc ${BINARY_ROOT_DIR}/*.ts 28# 2. Copies ${ROOT_DIR}/*.ts into ${BINARY_ROOT_DIR}/*.ts 29# 3. Compiles 'ts' project with tsc: 30# ${BINARY_ROOT_DIR}/*.ts -> ${BINARY_ROOT_DIR}/*.js 31# 4. Links all 'abc' files into single file: 32# ${BINARY_ROOT_DIR}/*.abc -> ${BINARY_ROOT_DIR}/lib_linked.abc 33# 5. Creates panda_ets_interop_js_test from ${BINARY_ROOT_DIR}/*.js and ${BINARY_ROOT_DIR}/lib_linked.abc 34# 6. Tests difference between expected and actual declaration files: 35# ${BINARY_ROOT_DIR}/*.ts <-> ${ROOT_DIR}/*.expected 36# 37# Example usage: 38# create_declgen_ets2ts_test(common 39# ROOT_DIR 40# ${CMAKE_CURRENT_SOURCE_DIR} 41# BINARY_ROOT_DIR 42# ${CMAKE_CURRENT_BINARY_DIR} 43# TS_MAIN 44# ${CMAKE_CURRENT_SOURCE_DIR}/main.ts 45# TS_SOURCES 46# ${CMAKE_CURRENT_SOURCE_DIR}/test.ts 47# JS_SOURCES 48# ${CMAKE_CURRENT_SOURCE_DIR}/test_dyn.js 49# ETS_SOURCES 50# ${CMAKE_CURRENT_SOURCE_DIR}/lib1.ets 51# ${CMAKE_CURRENT_SOURCE_DIR}/lib2.ets 52# DECLS_EXPECTED 53# ${CMAKE_CURRENT_SOURCE_DIR}/lib1.expected 54# ${CMAKE_CURRENT_SOURCE_DIR}/lib2.expected 55# ) 56function(create_declgen_ets2ts_test TARGET) 57 cmake_parse_arguments( 58 ARG 59 "" 60 "ROOT_DIR;BINARY_ROOT_DIR;TS_MAIN;ETS_VM_LAUNCHER;" 61 "TS_SOURCES;ETS_SOURCES;JS_SOURCES;DECLS_EXPECTED" 62 ${ARGN} 63 ) 64 65 set(TARGET "declgen_ets2ts_test_${TARGET}") 66 67 set(ALL_DYNAMIC_SOURCES) 68 if (DEFINED ARG_TS_SOURCES) 69 list(APPEND ALL_DYNAMIC_SOURCES ${ARG_TS_SOURCES}) 70 endif() 71 if (DEFINED ARG_JS_SOURCES) 72 list(APPEND ALL_DYNAMIC_SOURCES ${ARG_JS_SOURCES}) 73 endif() 74 if (DEFINED ARG_ETS_VM_LAUNCHER) 75 list(APPEND ALL_DYNAMIC_SOURCES ${ARG_ETS_VM_LAUNCHER}) 76 endif() 77 78 # Replaces path prefix from ARG_ROOT_DIR to ARG_BINARY_ROOT_DIR and extension 79 function(rebase_path SRC DST) 80 if(ARGC GREATER 2 AND ARGV2 STREQUAL "ts") 81 file(MAKE_DIRECTORY "${ARG_BINARY_ROOT_DIR}/glue_file") 82 string(REGEX REPLACE "^${ARG_ROOT_DIR}" "${ARG_BINARY_ROOT_DIR}/glue_file" RES ${SRC}) 83 else() 84 string(REGEX REPLACE "^${ARG_ROOT_DIR}" "${ARG_BINARY_ROOT_DIR}" RES ${SRC}) 85 endif() 86 if(ARGC GREATER 2) 87 set(NEW_EXT ${ARGV2}) 88 string(REGEX REPLACE "\.[a-zA-Z0-9]+$" ".${NEW_EXT}" RES ${RES}) 89 endif() 90 set(${DST} ${RES} PARENT_SCOPE) 91 endfunction() 92 93 set(JS_TO_ABC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/compiled_js) 94 95 # Create arktsconfig.json with "dynamicPaths" for js modules 96 set(ARKTSCONFIG_CONTENT 97 " }\n" 98 " }\n" 99 "}\n" 100 ) 101 set(COMMA "") 102 foreach(JS_SOURCE ${ARG_JS_SOURCES}) 103 get_filename_component(JS_SRC_WE ${JS_SOURCE} NAME_WE) 104 set(ARKTSCONFIG_CONTENT 105 " \"${JS_SRC_WE}\": {\"language\": \"js\", \"ohmUrl\":\"${JS_TO_ABC_OUTPUT_DIR}/${JS_SRC_WE}\"}${COMMA}\n" 106 "${ARKTSCONFIG_CONTENT}" 107 ) 108 if(COMMA STREQUAL "") 109 set(COMMA ",") 110 endif() 111 endforeach() 112 set(ARKTSCONFIG_CONTENT 113 "{\n" 114 " \"compilerOptions\": {\n" 115 " \"baseUrl\": \"${PANDA_ROOT}\",\n" 116 " \"paths\": {\n" 117 " \"std\": [\"${PANDA_ROOT}/plugins/ets/stdlib/std\"],\n" 118 " \"escompat\": [\"${PANDA_ROOT}/plugins/ets/stdlib/escompat\"]\n" 119 " },\n" 120 " \"dynamicPaths\": {\n" 121 "${ARKTSCONFIG_CONTENT}" 122 ) 123 set(ARKTSCONFIG ${CMAKE_CURRENT_BINARY_DIR}/arktsconfig.json) 124 file(WRITE ${ARKTSCONFIG} ${ARKTSCONFIG_CONTENT}) 125 126 # NOTE (kkonsw): temporary disabling all other checks 127 set(ETS_VERIFICATOR_ERRORS "NodeHasParent:EveryChildHasValidParent:VariableHasScope:NodeHasType:IdentifierHasVariable:ReferenceTypeAnnotationIsNull:ArithmeticOperationValid:SequenceExpressionHasLastType:ForLoopCorrectlyInitialized:VariableHasEnclosingScope:ModifierAccessValid") 128 # NOTE(dkofanov): `ImportExportAccessValid` need to be fixed 129 # set(ETS_VERIFICATOR_ERRORS "${ETS_VERIFICATOR_ERRORS}:ImportExportAccessValid") 130 131 # Compile source .ets files into .abc and declaration .ts files 132 set(ABC_FILES "") 133 set(DECL_FILES "") 134 set(GLUE_FILES "") 135 set(ABC_TARGETS "") 136 set(ETS_MODULE_KEY "") 137 foreach(ETS_SOURCE ${ARG_ETS_SOURCES}) 138 rebase_path(${ETS_SOURCE} ABC_PATH "abc") 139 list(APPEND ABC_FILES ${ABC_PATH}) 140 rebase_path(${ETS_SOURCE} DECL_PATH "d.ts") 141 list(APPEND DECL_FILES ${DECL_PATH}) 142 rebase_path(${ETS_SOURCE} GLUE_PATH "ts") 143 list(APPEND GLUE_FILES ${GLUE_PATH}) 144 145 add_custom_command( 146 OUTPUT ${ABC_PATH} ${DECL_PATH} ${GLUE_PATH} 147 COMMENT "Compiling: ${ETS_SOURCE}" 148 COMMAND $<TARGET_FILE:es2panda> ${ETS_MODULE_KEY} --arktsconfig ${ARKTSCONFIG} --output ${ABC_PATH} --extension=ets --ast-verifier:errors=${ETS_VERIFICATOR_ERRORS} ${ETS_SOURCE} 149 COMMAND $<TARGET_FILE:declgen_ets2ts> ${ETS_MODULE_KEY} --arktsconfig ${ARKTSCONFIG} --output-dets=${DECL_PATH} --output-ets=${GLUE_PATH} ${ETS_SOURCE} 150 DEPENDS es2panda declgen_ets2ts ${ETS_SOURCE} ${ARKTSCONFIG} 151 ) 152 153 get_filename_component(ABC_NAME ${ABC_PATH} NAME) 154 set(ABC_TARGET ${TARGET}_es2panda_${ABC_NAME}) 155 add_custom_target(${ABC_TARGET} 156 DEPENDS ${ABC_PATH} ${DECL_PATH} 157 ) 158 list(APPEND ABC_TARGETS ${ABC_TARGET}) 159 if(ETS_MODULE_KEY STREQUAL "") 160 set(ETS_MODULE_KEY "--ets-module") 161 endif() 162 endforeach() 163 164 set(COPIED_TS_SOURCES "") 165 set(JS_FILES "") 166 # Copy TS files into build folder and 167 # Compute destination JS file paths for these TS files 168 foreach(TS_SOURCE ${ARG_TS_SOURCES}) 169 rebase_path(${TS_SOURCE} COPIED_TS_SOURCE) 170 configure_file(${TS_SOURCE} ${COPIED_TS_SOURCE} COPYONLY) 171 list(APPEND COPIED_TS_SOURCES ${COPIED_TS_SOURCE}) 172 rebase_path(${TS_SOURCE} JS_SOURCE "js") 173 list(APPEND JS_FILES ${JS_SOURCE}) 174 endforeach() 175 176 # Compute destination JS file paths for generated TS declarations 177 foreach(TS_SOURCE ${GLUE_FILES}) 178 rebase_path(${TS_SOURCE} JS_SOURCE "js") 179 list(APPEND JS_FILES ${JS_SOURCE}) 180 endforeach() 181 182 # Compile source .ts and declaratin .ts files into .js 183 add_custom_command( 184 OUTPUT ${JS_FILES} 185 COMMENT "Compile ts files: ${COPIED_TS_SOURCES} ${DECL_FILES} ${GLUE_FILES}" 186 COMMAND ${PANDA_THIRD_PARTY_SOURCES_DIR}/typescript/bin/tsc --target es5 --strict --lib es2020,dom --outDir ${CMAKE_CURRENT_BINARY_DIR} ${COPIED_TS_SOURCES} ${DECL_FILES} 187 # COMMAND ${PANDA_THIRD_PARTY_SOURCES_DIR}/typescript/bin/tsc --target es5 --strict --outDir "${CMAKE_CURRENT_BINARY_DIR}" ${GLUE_FILES} 188 DEPENDS es2panda ark_link ${ABC_TARGETS} ${ARKTSCONFIG} ${COPIED_TS_SOURCES} ${DECL_FILES} 189 ) 190 add_custom_target(${TARGET}_tsc 191 DEPENDS ${JS_FILES} 192 ) 193 194 # Link .abc files into single .abc file 195 set(LIB_LINKED_ABC ${CMAKE_CURRENT_BINARY_DIR}/lib_linked.abc) 196 add_custom_command( 197 OUTPUT ${LIB_LINKED_ABC} 198 COMMENT "Linking ABC files: ${ABC_FILES}" 199 COMMAND $<TARGET_FILE:ark_link> --output ${LIB_LINKED_ABC} -- ${ABC_FILES} 200 DEPENDS ark_link ${ABC_TARGETS} ${ABC_FILES} 201 ) 202 add_custom_target(${TARGET}_link 203 DEPENDS ${LIB_LINKED_ABC} 204 ) 205 206 list(APPEND ALL_DYNAMIC_SOURCES ${DECL_FILES}) 207 list(APPEND ALL_DYNAMIC_SOURCES ${GLUE_FILES}) 208 209 # Execute compiled interop project 210 # PACKAGE_NAME is not necessary for declgen_ets2ts_test, 211 # but it is necessary for panda_ets_interop_js_test; 212 panda_ets_interop_js_test(${TARGET} 213 ABC_FILE ${LIB_LINKED_ABC} 214 JS_LAUNCHER ${ARG_TS_MAIN} 215 JS_SOURCES ${ALL_DYNAMIC_SOURCES} 216 DYNAMIC_ABC_OUTPUT_DIR ${JS_TO_ABC_OUTPUT_DIR} 217 PACKAGE_NAME "main" 218 ) 219 add_dependencies(${TARGET} ${TARGET}_tsc ${TARGET}_link) 220 add_dependencies(declgen_ets2ts_test ${TARGET}) 221 222 # Test difference between actual and expected declarations 223 list(LENGTH DECL_FILES DECL_LEN) 224 list(LENGTH ARG_DECLS_EXPECTED DECL_EXPECTED_LEN) 225 if(NOT DECL_LEN EQUAL DECL_EXPECTED_LEN) 226 message(FATAL_ERROR "create_declgen_ets2ts_test: number of source ets files is not equal to number of expected declarations") 227 endif() 228 math(EXPR DECL_LEN "${DECL_LEN} - 1") 229 foreach(IDX RANGE ${DECL_LEN}) 230 list(GET ARG_DECLS_EXPECTED ${IDX} DECL_EXPECTED) 231 list(GET DECL_FILES ${IDX} DECL_ACTUAL) 232 string(SHA1 DECL_ACTUAL_HASH "${DECL_ACTUAL}") 233 string(SHA1 DECL_EXPECTED_HASH "${DECL_EXPECTED}") 234 set(ACTUAL_CLEANED "${CMAKE_BINARY_DIR}/declaration_actual_${DECL_ACTUAL_HASH}.ts") 235 set(EXPECTED_CLEANED "${CMAKE_BINARY_DIR}/declaration_expected_${DECL_EXPECTED_HASH}.ts") 236 237 get_filename_component(DECL_NAME ${DECL_EXPECTED} NAME) 238 set(DIFF_TARGET ${TARGET}_diff_${DECL_NAME}) 239 240 # Remove multi-line comments 241 add_custom_command( 242 OUTPUT ${ACTUAL_CLEANED} 243 COMMAND sed '/^\\/\\*/,/\\*\\//d' ${DECL_ACTUAL} > ${ACTUAL_CLEANED} 244 DEPENDS ${DECL_ACTUAL} 245 ) 246 247 add_custom_command( 248 OUTPUT ${EXPECTED_CLEANED} 249 COMMAND sed '/^\\/\\*/,/\\*\\//d' ${DECL_EXPECTED} > ${EXPECTED_CLEANED} 250 DEPENDS ${DECL_EXPECTED} 251 ) 252 253 # Compare the modified files and remove them 254 add_custom_target(${DIFF_TARGET} 255 COMMENT "Test declgen ets2ts diff between ${DECL_ACTUAL} and ${DECL_EXPECTED} (ignoring comments)" 256 COMMAND ${CMAKE_COMMAND} -E compare_files ${ACTUAL_CLEANED} ${EXPECTED_CLEANED} 257 COMMAND ${CMAKE_COMMAND} -E remove ${ACTUAL_CLEANED} ${EXPECTED_CLEANED} 258 DEPENDS ${ACTUAL_CLEANED} ${EXPECTED_CLEANED} 259 ) 260 add_dependencies(declgen_ets2ts_test_diff ${DIFF_TARGET}) 261 endforeach() 262endfunction() 263 264 265add_subdirectory(async) 266add_subdirectory(basic_var) 267add_subdirectory(classes) 268add_subdirectory(enums) 269add_subdirectory(fields) 270add_subdirectory(functions) 271add_subdirectory(generics) 272add_subdirectory(getters_setters) 273add_subdirectory(imports) 274add_subdirectory(interface) 275add_subdirectory(methods) 276add_subdirectory(unions) 277add_subdirectory(depend_export) 278add_subdirectory(re_export) 279add_subdirectory(export_error) 280add_subdirectory(export_default) 281 282# interop not supported 283# eg: E/ets_interop_js: InteropCtx::Fatal: ets_proxy requested for Lescompat/WeakMap; must add or forbid 284# add_subdirectory(esvalue) 285# add_subdirectory(standard_lib) 286# add_subdirectory(properties) 287 288# error: [TID 006c83] E/ets_interop_js: InteropCtx::Fatal: Class lib.A has no constructor 289# a bug exists in interop. interop is being fixed 290# please see issue: #23096 291# add_subdirectory(namespace) 292 293# NOTE(aakmaev): need proper comparing. Issue #17097 294# add_subdirectory(global_vars) 295