• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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