diff --git a/static_core/plugins/ets/doc/interop_js/1_introduction.rst b/static_core/plugins/ets/doc/interop_js/1_introduction.rst index b3cd32a99393da8ebe51d57a3b843c941c69203c..b49fef94cc825d967df08834992715989fc0e447 100644 --- a/static_core/plugins/ets/doc/interop_js/1_introduction.rst +++ b/static_core/plugins/ets/doc/interop_js/1_introduction.rst @@ -14,70 +14,186 @@ Introduction ++++++++++++ -This document describe specification of interop between ArkTS runtime and -Typescript/Javascript, including additional compile time type checking for interop between -ArkTS and Typescript/Javascript. +Terminology explaination +------------------------ -Managed interop is part of runtime and frontend of ArkTS. It communicate -with javascript runtime via special native bridge. Here are excuted all -nessesary conversions for passed arguments. So all communication are only in -runtime. Additionally here can be typecheck for some cases at compile time. It -is just additional stage for better user experience, but it is does not affect -runtime part. ++-----------------+------------------------------------------------------------------------------------------+ +| Terminology | Explaination | ++=================+==========================================================================================+ +| ArkTS | The ArkTS with evolved ArkTS syntax and semantics | ++-----------------+------------------------------------------------------------------------------------------+ +| TS | abbreviation for Typescript | ++-----------------+------------------------------------------------------------------------------------------+ +| JS | abbreviation for Javascript | ++-----------------+------------------------------------------------------------------------------------------+ +| interop | abbreviation for interoperation | ++-----------------+------------------------------------------------------------------------------------------+ +| CTE | abbreviation for compile time error | ++-----------------+------------------------------------------------------------------------------------------+ +| RTE | abbreviation for runtime error | ++-----------------+------------------------------------------------------------------------------------------+ +| UB | abbreviation for undefined behavior | ++-----------------+------------------------------------------------------------------------------------------+ +| basic operators | property access ``.``, invocation ``()``, index access ``[]``, and instantiation ``new`` | ++-----------------+------------------------------------------------------------------------------------------+ + +Background +---------- + +With evolution of ArkTS language, ArkTS will provide more language features and some syntax and semantics also evolve. Moreover, ArkTS native compiler with complete type checking capabilities will be introduced. Althrough is not mandatory to migrate existing ArkTS and TS/JS code to Evolved ArkTS. However, for those developers who want to migrate, it is necessary to provide interoperability between ArkTS and TS/JS for better migration experiencen and for the requirement of reusing existing code assets. This document shows how ArkTS interoperates with TS/JS, which is helpful in the following scenarios: + +- migrate existing code to ArkTS + +- reuse some libraries of TS/JS code in migrated ArkTS modules + +We will elaborate interop rules in the upcoming chapters. Before that we emphasize that we basically provide these rules in the way of "white list", which means that if some scenarios are not mentioned, then they are not supported. For unsupported scenarios, there may be CTE or RTE or UB. In the future we may extend our "white list" and some unsupported scenarios will become supported, but before that unsupported scenarios should be avoided for better stability. + +Managed interop is part of runtime and frontend of ArkTS. In runtime ArkTS communicates with TS/JS via special native bridge. Additionally there can be typecheck for some cases at compile time. It is just additional stage for better user experience, but it is independent with runtime part. + +This document describes specification of interop between ArkTS and TS/JS, and additional compile time type checking for interop between ArkTS and TS/JS. Interop via 'import' and import rules ------------------------------------- + Our interop can be made via `import`, like what we have done in TS. However, we do have some rules for import directions. -- ArkTS files can import TS/JS files, +- ArkTS files can import TS/JS files, with additional restrictions: - with additional restrictions: 1. ArkTS class cannot `extends` TS/JS class 2. ArkTS class cannot `implements` TS interfaces - TS/JS files cannot import ArkTS files -Basic principles ----------------- +For now we only support the syntax ``"import {something} from 'path'"`` for interop import scenarios, and other import syntax, such as ``"import {something as alias} from 'path'"`` and ``"import defaultSomething from 'path'"`` and ``"import * as something from 'path'"``, is not supported. + +Some preliminaries about ArkTS +--------------------------------------- + +Here we list some important points for completeness. These points should be able to be implied by ArkTS language specification. + +ArkTS static semantics +====================== + +- ArkTS has static nominal type system and structural typing is forbidden. +- There is complete strict type checking during ArkTS compilation and execution. +- The layout of ArkTS objects cannot be dynamically changed. For example, it is forbidden to add/delete fields or methods of ArkTS classes and its instances. It is also forbidden to assign filed with a value whose type is different from the type of field declaration. +- There is runtime type check for implicit and explicit type conversion. + +ESObject in ArkTS +================= + +- ESObject is a special type, which is independent of Object type. +- ESObject can be used as type annotation and type parameter in generics. +- ESObject can be used to wrap data and objects from TS/JS and ArkTS. In particular, it can be used to wrap null and undefined. +- Basic operators and explicit type conversion on object of ESObject type are supported without compilation type check. And result type of basic operators on object of ESObject is still ESObject. +- Types in ArkTS can be implicitly or explicitly converted to ESObject types, but ESObject is not allowed to be implicitly converted to other types of ArkTS. +- It is not allowed to defined Object literals of ESObject type. + +Note: Abusing ESObject is strongly not recommended, because type checking for ESObject capability is weakened at compile time, which can easily leave coding errors to runtime. Also, there will be additional execution logics for operations on ESObject at runtime, resulting in worse runtime performance. + +Note: Using ESObject as type arguments in generics is not supported for now. + +Examples +******** + +.. code-block:: typescript + :linenos: -- In the ArkTS environment, when executing the ArkTS code logic and encountering an object that is incompatible with the annotated type, a runtime exception will occur. + // ArkTS code + class A { + v: number = 123 + } + function foo(x: ESObject) {} -- ArkTS objects layout cannot be dynamically modified. + let a: ESObject = new A() // OK, implicitly convert A to ESObject + a.v // OK + a[0] // no CTE, but RTE, a is not indexable + a() // no CTE, but RTE, a is not a function + new a() // no CTE, but RTE, a is not a constructor -- Type conversion (explicit or implicit) in ArkTS will cause runtime type verification, and will generate runtime exceptions if conversion is not possible in proper way. + let n1: number = a.v // CTE, cannot implicitly convert ESObject to number + let n2: number = a.v as number // OK + let n3: ESObject = a.v // OK + a.v + 1 // CTE, no '+' operation between ESObject and number + (a.v as number) + 1 // OK + + let s1: ESObject = 1 // OK, implicitly convert number to ESObject + let s2: ESObject = new A() // OK, implicitly convert A to ESObject + let s3: ESObject = 1 as ESObject // OK, explicitly convert number to ESObject + let s4: ESObject = new A() as ESObject; // OK, explicitly convert A to ESObject + + foo(1); // OK, implicitly convert number to the ESObject + foo(new A()) // OK, implicitly convert A to ESObject + + let point: ESObject = {x: 0, y: 1} // CTE, cannot create object literal of type ESObject + + foo({x: 0, y: 1}) // CTE, cannot create object literal of type ESObject + + class G { + foo(x: T) {} + } + + new G() // OK + new G() // CTE, cannot use ESObject as type arguments in generics + +- If basic operators on objects of type ESObject cannot be done properly, a runtime exception will be thrown. + +.. code-block:: typescript + :linenos: + + // ArkTS code + let x: ESObject = undefined + x[0] // RTE, x is not indexable + x() // RTE, x is not a function + x.f // RTE, cannot access property of undefined + new x() // RTE, x is not a constructor + x as string // RTE, cannot cast undefined to string + +Primitive types in ArkTS +================================= + +In ArkTS, there are the following primitive types: + +- number +- byte +- short +- int +- long +- float +- double +- bigint +- string +- boolean +- undefined +- null Principles for compilation type check ------------------------------------- - Support use TS types in ArkTS files as type annotations. +- In ArkTS, everything imported from JS has type ESObject. + - Compile-time type checking should be checked according to the rules of the file type: ArkTS files should follow the type checking rules of ArkTS, TS files should follow the type checking rules of TS. The interop part will be checked based on :ref:`Principles for compilation type mapping rules`, after type mapping to the type of the file where it is located. - When the ArkTS files are compiled into bytecode, all type annotations from TS in the ArkTS files will degenerate into ESObject. -- When the objects imported from TS/JS in the ArkTS file are finally compiled into bytecode, the types of these objects will be treated as ESObject. +- When the ArkTS files are compiled into bytecode, the types of all objects imported from TS/JS will degenerate into ESObject. .. _Principles for compilation type mapping rules: Principles for compilation type mapping rules --------------------------------------------- - - Primitive types are mapped into primitive types(e.g number -> number).(see :ref:`Typecheck conversion rules. Primitive values`) - Composed types (classes/interfaces/structs) are mapped into composed types. Moreover, nested types will be mapped into nested types.(e.g interface Y {x: X, s: string} -> interface Y {x: X, s: string}) (see :ref:`Typecheck conversion rules. Reference values`) -Principles for runtime objects mapping rules +Principles for runtime mapping rules -------------------------------------------- -- Primitive types will be mapped into primitive types (except special cases, see :ref:`Conversion rules Primitive values`) - -- ArkTS reference types will be mapped into some proxy objects in JS runtime - -- JS runtime objects will be mapped into `ESObject` in ArkTS runtime - +- Primitive types will be mapped into primitive types (except special cases, see :ref:`Conversion rules Primitive values`). -Terminology ------------ +- ArkTS reference types will be mapped into some proxy objects in TS/JS. -Throughout the docs we may often refer "CTE" by "Compile Time Error" and "RTE" by "Runtime Time Error". +- TS/JS objects will be mapped into `ESObject` in ArkTS runtime. diff --git a/static_core/plugins/ets/doc/interop_js/2_esobject.rst b/static_core/plugins/ets/doc/interop_js/2_esobject.rst deleted file mode 100644 index 7f43418d740cdc45215240b4462b7c1f7d852603..0000000000000000000000000000000000000000 --- a/static_core/plugins/ets/doc/interop_js/2_esobject.rst +++ /dev/null @@ -1,100 +0,0 @@ -.. - 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. - -.. _ESObject: - -++++++++++++++++++++ -ESObject in ArkTS -++++++++++++++++++++ - -- ESObject type is a special type in ArkTS. It is separate from Object type. -- ESObject type can be used in following ways without compliation type check: ``operator new``, ``operator []``, ``operator ()``, ``operator .``, ``operator as``. Moreover, the types of results of ``operator new``, ``operator []``, ``operator ()``, ``operator .`` are still ESObject and they will be called on JS-side. -- In bytecode of ArkTS, all entities imported from TS/JS will be of type ESObject. -- Values of ESObject type can be converted to and from Object type. However, implicitly converting an object of ESObject type to any other type is forbidden. -- Values of ESObject type may wrap entities from TS/JS, they also may wrap normal objects of types in ArkTS. -- ESObject can be used as type parameters in generics. -- It is not allowed to define an object literal of type ESObject. - -Examples -******** - -.. code-block:: javascript - :linenos: - - // test.js - class A { - v = 123 - } - export let a = new A() - - export function foo(v) {} - -.. code-block:: typescript - :linenos: - - // app.ets - import { a, foo } from './test' // a is of ESObject type - a.v // ok - a[index] // ok, will be called operator [] on JS-side - a() // ok, no CTE, but RTE, no operation () on JS side - new a() // no CTE, but RTE, no operation new on JS side - - let n1: number = a.v // CTE - let n2: number = a.v as number // ok - let n3: ESObject = a.v // ok - a.v + 1 // CTE - (a.v as number) + 1 // ok - - let s1: ESObject = 1; // ok, implicit conversion - let s2: ESObject = new StaticClass() // ok, implicit conversion - let s3: ESObject = 1 as ESObject; // ok, explicit conversion - let s4: ESObject = new StaticClass() as ESObject; // ok, explicit conversion - - foo(1); // ok, implicitly convert 1 to the ESObject type - foo(new StaticClass()); // ok, implicitly convert static object to the ESObject type - - let arr = new Array(); // ok, ESObject is used as a type parameter - - let point: ESObject = {x: 0, y: 1}; // CTE, cannot create object literal of type ESObject - - foo({x: 0, y: 1}); // CTE, cannot create object literal of type ESObject - -- When using ``as`` keyword if ArkTS type doesn't map to JS type then a runtime exception will be thrown. - -.. code-block:: typescript - :linenos: - - // file1.js - export x = 1; - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - import { x } from "file1"; - const valStr = x as string; // RTE, cannot cast number to string - -- When primitive type values are copied to ArkTS they become ESObject that contains primitive value. - In that case operators ``[]``, ``()``, ``.``, and ``new`` have no meaning and their usage will throw an exception. - -.. code-block:: typescript - :linenos: - - // file1.js - export x = 1; - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - import { x } from "file1"; - const val = new x(); // RTE, no operation new on JS side diff --git a/static_core/plugins/ets/doc/interop_js/3_conversions_type_check.rst b/static_core/plugins/ets/doc/interop_js/3_conversions_type_check.rst index 05178411876104f2afe5f537c9281fe9ef0d6b96..9e84543eb78f506e986b8760783448522ffb9093 100644 --- a/static_core/plugins/ets/doc/interop_js/3_conversions_type_check.rst +++ b/static_core/plugins/ets/doc/interop_js/3_conversions_type_check.rst @@ -16,9 +16,7 @@ Typecheck conversion rules ++++++++++++++++++++++++++ -Typecheck performs only for ArkTS/TS files. - -Let describe the relationships: +Typecheck performs only for ArkTS/TS files. Let us describe the relationships: 1. ArkTS to TS type conversion 2. TS to ArkTS type conversion @@ -34,23 +32,23 @@ ArkTS to TS type conversion +-------------------------+-------------------------+ | ArkTS | TS | +=========================+=========================+ -| ``number/Number`` | ``Number`` | +| ``number/Number`` | ``number`` | +-------------------------+-------------------------+ -| ``byte/Byte`` | ``Number`` | +| ``byte/Byte`` | ``number`` | +-------------------------+-------------------------+ -| ``short/Short`` | ``Number`` | +| ``short/Short`` | ``number`` | +-------------------------+-------------------------+ -| ``int/Int`` | ``Number`` | +| ``int/Int`` | ``number`` | +-------------------------+-------------------------+ -| ``long/Long`` | ``Number`` | +| ``long/Long`` | ``number`` | +-------------------------+-------------------------+ -| ``float/Float`` | ``Number`` | +| ``float/Float`` | ``number`` | +-------------------------+-------------------------+ -| ``double/Double`` | ``Number`` | +| ``double/Double`` | ``number`` | +-------------------------+-------------------------+ | ``char/Char`` | ``string`` | +-------------------------+-------------------------+ -| ``boolean/Boolean`` | ``Boolean`` | +| ``boolean/Boolean`` | ``boolean`` | +-------------------------+-------------------------+ | ``string/String`` | ``string`` | +-------------------------+-------------------------+ @@ -77,9 +75,9 @@ TS to ArkTS type conversion +--------------------------+-------------------------+ | TS | ArkTS | +==========================+=========================+ -| ``number/Number`` | ``Number`` | +| ``number/Number`` | ``number`` | +--------------------------+-------------------------+ -| ``boolean/Boolean`` | ``Boolean`` | +| ``boolean/Boolean`` | ``boolean`` | +--------------------------+-------------------------+ | ``string/String`` | ``string`` | +--------------------------+-------------------------+ @@ -103,7 +101,7 @@ TS to ArkTS type conversion +--------------------------+-------------------------+ | ``void(variable type)`` | ``undefined`` | +--------------------------+-------------------------+ -| ``void(return type)`` | ``void`` | +| ``void(return type)`` | ``void`` | +--------------------------+-------------------------+ | ``never`` | ``never`` | +--------------------------+-------------------------+ @@ -182,7 +180,6 @@ Interfaces: export class MyClass implements MyInface { data: number = 0; } - export type MyFunction = Function; .. code-block:: typescript diff --git a/static_core/plugins/ets/doc/interop_js/4_conversions_runtime.rst b/static_core/plugins/ets/doc/interop_js/4_conversions_runtime.rst index d56019c057e5fd5ee3046f5f36b8a5b72d82feb3..9818f9d12b19692a85e780f1e0c90734e833e2f0 100644 --- a/static_core/plugins/ets/doc/interop_js/4_conversions_runtime.rst +++ b/static_core/plugins/ets/doc/interop_js/4_conversions_runtime.rst @@ -18,14 +18,14 @@ Runtime conversion rules Runtime conversion rules: Primitive values ****************************************** -Primitive type values are copied between ArkTS runtime and JS runtime by value. +Primitive type values are copied by value during interop runtime. If the value is changed in one runtime it doesn't affect another one. ArkTS to JS conversion -======================= +====================== +-------------------------+-------------------+ -| ArkTS runtime type | JS runtime type | +| ArkTS type | JS runtime type | +=========================+===================+ | ``number/Number`` | ``number`` | +-------------------------+-------------------+ @@ -51,141 +51,53 @@ ArkTS to JS conversion +-------------------------+-------------------+ | ``enum`` | ``number/string`` | +-------------------------+-------------------+ -| ``literal type string`` | ``string`` | -+-------------------------+-------------------+ | ``undefined`` | ``undefined`` | +-------------------------+-------------------+ | ``null`` | ``null`` | +-------------------------+-------------------+ -- Numeric ArkTS types map to JS ``number``. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsInt: int = 1; - export let etsDouble: double = 2.1; +- Boxed types(e.g. Number, Char, etc) map to primitive JS types. .. code-block:: javascript :linenos: // file1.js - import { etsInt, etsDouble } from "file2"; - - let jsInt = etsInt; // jsInt is 'number' and equals 1 - let jsDouble = etsDouble; // jsDouble is 'number' and equals 2.1 - -- ArkTS ``boolean`` maps to JS ``boolean``. + export function foo(x) { + console.log(typeof x) + console.log(x) + } .. code-block:: typescript :linenos: // file2.ets ArkTS - export let etsBool: boolean = true; - -.. code-block:: javascript - :linenos: - - // file1.js - import { etsBool } from "file2"; - - let jsBool = etsBool; // jsBool is 'boolean' and equals true - -- ArkTS ``string`` maps to JS ``string``. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsStr: string = "hello"; - -.. code-block:: javascript - :linenos: - - // file1.js - import { etsStr } from "file2"; - - let jsStr = etsStr; // jsStr is 'string' and equals "hello" - -- ArkTS ``bigint`` maps to JS ``bigint``. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsBigInt: bigint = 10n; - -.. code-block:: javascript - :linenos: + import { foo } from 'file1' + export let x: Number = new Number(123) + foo(x) // print 'number' and '123' - // file1.js - import { etsBigInt } from "file2"; - - let jsBigInt = etsBigInt; // jsBigInt is 'bigint' and equals 10 - -- ArkTS ``undefined`` maps to JS ``undefined``. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsUndef: undefined = undefined; +- ``enum`` conversion depends on the type of enumeration. Numeric ``enum`` converts to ``number``. String ``enum`` converts to ``string``. .. code-block:: javascript :linenos: // file1.js - import { etsUndef } from "file2"; - - let jsUndef = etsUndef; // jsUndef is 'undefined' and equals undefined - -- ArkTS ``null`` maps to JS ``null``. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsNull: null = null; - -.. code-block:: javascript - :linenos: - - // file1.js - import { etsNull } from "file2"; - - let jsNull = etsNull; // jsNull is 'object' and equals null - -- Boxed types(e.g. Number, Char, etc) map to primitive JS types. - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let x: Number = 1; // x is 'object' - -.. code-block:: javascript - :linenos: - - // file1.js JS - import { x } from "file2"; - - let a = x; // x is 'number' and equals 1 + export function foo(x) { + console.log(typeof x) + console.log(x) + } -- ``enum`` conversion depends on the type of enumeration. Numeric ``enum`` converts to ``number``. String ``enum`` converts to ``string``. .. code-block:: typescript :linenos: // file2.ets ArkTS - // numeric enum + import { foo } from 'file1' enum Direction { Up = -1, Down = 1 } - let up: Direction = Direction.Up; - let down: Direction = Direction.Down; + foo(Direction.Down) // print 'number' and '1' // string enum enum Color { @@ -193,38 +105,7 @@ ArkTS to JS conversion Red = 'red' } - let green: Color = Color.Green; - let red: Color = Color.Red; - -.. code-block:: javascript - :linenos: - - // file1.js - import { up, down, green, red } from "file2"; - - let a = up; // a is 'number' and equals -1 - let b = down; // b is 'number' and equals 1 - - let c = green; // c is 'string' and equals 'green' - let d = red; // d is 'string' and equals 'red' - -- ``literal type string`` map to JS ``string`` - -.. code-block:: typescript - :linenos: - - // file2.ets ArkTS - export let etsLiteral: "literal" = "literal"; - etsLiteral = "not literal"; // compilation error - -.. code-block:: javascript - :linenos: - - // file1.js - import { etsLiteral } from "file2"; - - let val = etsLiteral; // val is "literal" but it can be changed - val = "not literal"; // ok + foo(Color.Red) // print 'string' and 'red' JS to ArkTS conversion ======================= @@ -358,49 +239,13 @@ Value imported from JS to ArkTS, should be converted explicitly using ``as`` key // file2.ets ArkTS import { jsSymbol } from "file1"; - let val = jsSymbol; // ok, val is ESObject + let val = jsSymbol; // OK, val is ESObject Limitations =========== -Object wrapper types --------------------- - -- Object wrapper types for primitive values such as ``Null``, ``Undefined``, ``Boolean``, ``Number``, ``Bigint``, ``String``, and ``Symbol`` - can't be copied by default to ArkTS values. It need special way for creating on JS side via ``new`` keyword. Without it even in - case of capital letter it will be primitive type according JS. - -.. code-block:: typescript - :linenos: - - // file1.js - let a = new Number(123); // typeof a is "object" - let b = Number(123); // typeof a is "number" - - // file2.ets ArkTS - import { a, b } from "file1"; - let aa = a as number; // RTE, as a is a reference from JS runtime - let bb = b as number; // ok, as b is a primitive number from JS runtime - -Solutions -^^^^^^^^^ - -- Use ``valueOf`` to get primitive values from wrapper objects and copy them to ArkTS - -.. code-block:: typescript - :linenos: - - // file1.js - let a = new Number(123); // typeof a == "object" - let b = Number(123); // typeof a == "number" - - // file2.ets ArkTS - import { a, b } from "file1"; - let aa = a.valueOf() as number; // ok - let bb = b as number; // ok - Copy semantic -============= +------------- - Primitive type value is copied from JS runtime to ArkTS runtime by value so there is no connection with JS runtime after compilation and no side effects. E.g. if Prototype is changed in JS runtime it won't be changed in ArkTS runtime. @@ -435,7 +280,7 @@ Copy semantic let num = a as number; // num is just static number with val 3 Solutions -========= +^^^^^^^^^ - Instead of importing primitive types, global contex can be imported instead of them and manipulation can be done through global context @@ -479,11 +324,16 @@ Wide limitation .. code-block:: typescript :linenos: + // file1.js + export function foo(x) { + console.log(x) + } + // file2.ets ArkTS - export let a: long = Math.pow(2, 53) + 10; + import { foo } from "file1" - // file1.js - import { a } from "file2"; // this import will result in precision loss + let a: long = Math.pow(2, 53) + 10; + foo(a); // printed value will not equal Math.pow(2, 53) + 10 because of precision loss - Integer ``number`` values when converted to ArkTS may have precision loss if a value out of range of ArkTS type @@ -525,7 +375,7 @@ Solutions // file2.js import { a } from "file1"; - let num = a; // ok, bigint no precision loss + let num = a; // OK, bigint no precision loss - Using ``number`` instead of ``float`` @@ -540,7 +390,7 @@ Solutions // file2.ets ArkTS import { a } from "file1"; - let x = a as number; // ok, will be correct + let x = a as number; // OK, will be correct let y = b as float; // may lose precision, use ``number`` type instead of float .. _Conversion rules Reference values: @@ -577,32 +427,45 @@ ArkTS to JS conversion - Proxing ArkTS object. +.. code-block:: javascript + :linenos: + + // file1.js + export function foo(a) { + a.val = "222"; // OK + a.newVal = "hello"; // RTE, objects are sealed + a.val = 123; // RTE, field has another type + } + .. code-block:: typescript :linenos: // file2.ets ArkTS + import { foo } from "file1" class A { val : string = "hi"; }; - export let a = new A(); + let a = new A(); + foo(a); + +- Inheritance also will be constructed for proxy classes .. code-block:: javascript :linenos: // file1.js - import { a } from 'file2' - a.val = "222"; // ok - - Reflect.set(a, "newVal", "hello"); // runtime exception, objects are sealed - Reflect.set(a, "val", 123); // runtime exception, field has another type - -- Inheritance also will be constructed for proxy classes + export function foo(a) { + // Classes A and B will be constructed on JS side with inheritance relationships. + a.vala = "222"; // OK + a.valb = "333"; // OK + } .. code-block:: typescript :linenos: // file2.ets ArkTS + import { foo } from 'file1' class B { valb = "b"; }; @@ -612,15 +475,7 @@ ArkTS to JS conversion }; let a = new A(); - -.. code-block:: javascript - :linenos: - - // file1.js - import { a } from 'file2' - // Classes A and B will be constructed on JS side with inheritance relationships. - a.vala = "222"; // ok - a.valb = "333"; // ok + foo(a); - About proxing ArkTS ``union`` see :ref:`Features ArkTS Union` - About proxing ArkTS ``tuple`` see :ref:`Features ArkTS Tuple` @@ -634,79 +489,65 @@ Limitations - Layout of ArkTS objects can not be changed and it is root of limitations for proxy-objects +.. code-block:: javascript + :linenos: + + // file1.js + export function foo(a) { + a.val = "222"; // OK + a.newVal = "hello"; // RTE, objects are sealed + a.val = 123; // RTE, field has another type + } + .. code-block:: typescript :linenos: // file2.ets ArkTS + import { foo } from "file1" class A { val : string = "hi"; }; - export let a = new A(); - -.. code-block:: javascript - :linenos: - - // file1.js + let a = new A(); + foo(a); - import {a} from 'file2' - a.newVal = 1; // runtime exception, objects are sealed - a.val = 123; // runtime exception, field has another type - a.val = "123"; // ok Solutions ^^^^^^^^^ - All changes for static classes should be done by user on static side +.. code-block:: javascript + :linenos: + + // file1.js + export function foo(a) { + a.val = "222"; // OK + a.newVal = "hello"; // OK + a.val = 123; // OK + } + .. code-block:: typescript :linenos: // file2.ets ArkTS + import { foo } from "file1" class A { - val : number|string = 2; - newVal : number = 3; + val : string | number = "hi"; + newVal: number = 0; }; - export let a = new A(); - -.. code-block:: javascript - :linenos: - - // file1.js - - import {a} from 'file2' - a.newVal = 1; // ok - a.val = 123; // ok - a.val = "123"; // ok + let a = new A(); + foo(a); -2. JS to ArkTS conversion +JS to ArkTS conversion ============================ In JS everything that is not a primitive value is an object. We will call it a reference value and it follows the reference conversion rules described in this chapter. -We can group all reference values into the following categories. - -+----------------------------------+ -| JS reference types | -+==================================+ -| ``Object`` | -+----------------------------------+ -| ``Class`` | -+----------------------------------+ -| ``Function`` | -+----------------------------------+ -| ``Collection`` | -| | -| ``(Array, Set, Map, etc)`` | -+----------------------------------+ -| ``Other standard builtins`` | -| | -| ``(Date, RegExp, Promise, etc)`` | -+----------------------------------+ - -ESObject is used to proxy any reference values from JS. - -- Proxing JS object with ESObject. + +ESObject can used to wrap any reference values from JS. + +- Wrapping JS object with ESObject. .. code-block:: javascript :linenos: @@ -724,11 +565,11 @@ ESObject is used to proxy any reference values from JS. // file2.ets ArkTS import { a } from 'file1' - let b = a; // ok, ``b`` is ESObject - let c = a.v; // ok, ``c`` is ESObject - let d = a.v as number; // ok, ``d`` is number + let b = a; // OK, ``b`` is ESObject + let c = a.v; // OK, ``c`` is ESObject + let d = a.v as number; // OK, ``d`` is number -- Special operators: ``new``, ``.``, ``[]``, ``()`` will work properly with ESObject, if such operations available on JS side, otherwise it will generate runtime exception +- Basic operators will work properly with ESObject, if such operations available on JS side, otherwise it will generate runtime exception .. code-block:: javascript :linenos: @@ -746,12 +587,12 @@ ESObject is used to proxy any reference values from JS. // file2.ets ArkTS import { a } from 'file1' - let number1: number = a.v as number // ok - a.v = 456; // ok, will modify original JS object - a.newfield = "hi"; // ok, will modify original JS object and create new field - let missedFiled = a.missedFiled as undefined; // ok - let number2 = a["v"] as number; // ok, will return 456 - let number2 = a[1] as undefined; // ok + let number1: number = a.v as number // OK + a.v = 456; // OK, modify original JS object + a.newfield = "hi"; // OK, modify original JS object and create new field + let missedFiled = a.missedFiled as undefined; // OK + let number2 = a["v"] as number; // OK, get 456 + let number2 = a[1] as undefined; // OK - Prototype of JS object can be modified on ArkTS side and it will be applied to all instances of Class @@ -760,7 +601,6 @@ ESObject is used to proxy any reference values from JS. // file1.js export class A { - v = 123; testFunction() { return true; } @@ -786,10 +626,7 @@ ESObject is used to proxy any reference values from JS. - About proxing collections and other standard builtins see :ref:`JS Std library` and :ref:`Async and concurrency features JS`. Limitations -=========== - -Unsupported operations ----------------------- +----------- - All unsupported special operations will throw runtime exception. Or incorrect conversions. @@ -817,58 +654,51 @@ Unsupported operations a[1] as int; // RTE a["v"] as string; // RTE - -Solutions -^^^^^^^^^ - -- If you need non standard conversion, you should use conversion for static types +- ESObject which contains reference type values from JS runtime can't be cast to ArkTS object. .. code-block:: javascript :linenos: // file1.js - - class A { - v = 123 + export class A { + v = 123; } export let a = new A() - .. code-block:: typescript :linenos: // file2.ets ArkTS import { a } from 'file1' - let num = a.v as number; // ok - let str = num.toString(); // ok, now we get static string from number + let b = a as Object; // RTE. a is ESObject with reference values from JS runtime. -Cast to static object ---------------------- +Solutions +^^^^^^^^^ -- ESObject which contains reference type values from JS runtime can't be cast to ArkTS object. +- If you need non standard conversion, you should use conversion for static types .. code-block:: javascript :linenos: // file1.js - export class A { - v = 123; + + class A { + v = 123 } export let a = new A() + .. code-block:: typescript :linenos: // file2.ets ArkTS import { a } from 'file1' - let b = a as Object; // RTE. a is ESObject with reference values from JS runtime. - -Solutions -^^^^^^^^^ + let num = a.v as number; // OK + let str = num.toString(); // OK, now we get static string from number - Only primitive types can be cast to ArkTS objects. @@ -886,7 +716,7 @@ Solutions :linenos: // file2.ets ArkTS - import { a } from './file1' + import { a } from 'file1' - let b: number = a.v as number; // ok - let c: Object = a.v as Object; // ok + let b: number = a.v as number; // OK + let c: Object = a.v as Object; // OK diff --git a/static_core/plugins/ets/doc/interop_js/5_js.rst b/static_core/plugins/ets/doc/interop_js/5_js.rst index b50f8f171d39b7a03165a03f59c19921d92d1019..2b71725a7619f0e7151e8a0d46b0a707293e88b4 100644 --- a/static_core/plugins/ets/doc/interop_js/5_js.rst +++ b/static_core/plugins/ets/doc/interop_js/5_js.rst @@ -919,18 +919,151 @@ Like other looping statements, you can use control flow statements inside statem * while + +Interop rules +^^^^^^^^^^^^^ + +- If try to iterate an object from ArkTS2.0 in JS world. The object should in ArkTS2.0 world must be iterable(can be used in for-of statements). Otherwise, the runtime will throw an error. + +.. code-block:: javascript + :linenos: + + // file1.js JS + export function display(iterable) { + for (let each of iterable) { + console.log(each) + } + } + +.. code-block:: typescript + :linenos: + + // file2.ets ArkTS2.0 + import { display } from './file1'; + + class Foo { + data: number[] = [1, 2, 3, 4, 5]; + + $_iterator(): FooIterator { + return new FooIterator(this); + } + } + + class FooIterator implements Iterator { + private metadata: Foo; + private index: int = 0; + + constructor(metadata: Foo) { + this.metadata = metadata; + } + + next(): IteratorResult { + + if (this.index < this.metadata.data.length) { + + return { + done: false, + value: this.metadata.data[this.index++] + }; + } else { + return { + done: true, + value: 0 + }; + } + } + } + + display(new Foo()); // ok, display will iterate over Foo object + display([1, 2, 3]); // ok, display will iterate over array + display(123); // error, 123 is not iterable + Relational operators: ``<``, ``>``, ``<=``, ``>=`` (empty) *********************************************************** -* ``<``, ``>``, ``<=``, ``>=`` operators +Description +^^^^^^^^^^^ + +Operators ``<``, ``>``, ``<=``, ``>=`` are used to compare the order of two operands. If the condition is true, the result is ``true``; otherwise, it is ``false``. + +.. code-block:: javascript + :linenos: + + let foo = 123; + let bar = 456; + + // Expected output: true + console.log(foo <= bar); + +Interop rules +^^^^^^^^^^^^^ + +- If one of the operands is from ArkTS2.0, the operands's type converted to JS must be the primitive type. Otherwise, the runtime will throw an error. + + +.. code-block:: javascript + :linenos: + + // file1.js + export function is_greator(a, b) { + return a > b + } + +.. code-block:: typescript + :linenos: + + // file2.ets ArkTS2.0 + import { is_greator } from './file1' + + // Ok, both operands's type in JS World(converted) + // are the same primitive type(number) + + let res = is_greator(1, 2); // ok + + // Error, operands's type in JS World(converted) + // are not the same type + let res = is_greator(1, "2"); // error + + // Error, operands's type in JS World(converted) + // are not the primitive type + class Foo { + a: Number; + } + let res = is_greator(new Foo(123), new Foo(456)); // error Relational operators: ``in`` (empty) ************************************* +Description +^^^^^^^^^^^ + +``${name} in ${object}`` returns the bool value ``true`` if there is a property ``name`` in the object ``${object}`` (or in its prototype chain). +Throw an runtime error if the ``${object}`` is not an object. + +.. code-block:: javascript + :linenos: + + let foo = { bar: "bar_value"}; + + console.log("bar" in foo); // true + console.log(undefined in foo); // false + // console.log("bar" in "not a object"); // error: not an object + console.log("length" in new String("it is a object")); // true: it is an object + console.log(Symbol.iterator in new String("it is a object")) // check the iterator + + +Interop rules +^^^^^^^^^^^^^ + In to getter/setter property works as expected. So, no additional actions are required. + + + + Relational operators: ``instanceof`` (empty) ********************************************* -* ``instanceof`` operator +Description +^^^^^^^^^^^ Operator ``instanceof`` checks whether an object belongs to a certain class. In other words, object instanceof constructor checks if an object is present constructor.prototype in the prototype chain object. @@ -951,9 +1084,20 @@ Operator ``instanceof`` checks whether an object belongs to a certain class. In console.log(auto instanceof Object); // Expected output: true +Interop rules +^^^^^^^^^^^^^ + +LHS instanceof RHS +- if one and only one of the operands is from ArkTS2.0, the operator will only make sense if it's primitive type. Otherwise, return false. +- if both operands are from ArkTS2.0, the operator will make no sense. + +TODO: to be degussed. + Closure (empty) *************** +Closure provides access to the outer scope of a function from inside the inner function, even after the outer function has closed. + Description ^^^^^^^^^^^ @@ -977,7 +1121,63 @@ Description // calling outer function greet('John'); // Hi John -Closure provides access to the outer scope of a function from inside the inner function, even after the outer function has closed. +Interop rules +^^^^^^^^^^^^^ + +- The closure in JS world will work as expected. So, no additional actions are required. + + +.. code-block:: javascript + :linenos: + + // js file + // handler.js + let handler = null; + + export function initHandler(foo) { + function my_handler() { + console.log("in my_handler"); + console.log(foo.bar); + } + + handler = my_handler; + } + + export function getHandler() { + if (handler === null) { + throw new Error('Handler is not set'); + } + return handler; + } + +.. code-block:: typescript + :linenos: + + // arkts 2.0 file + // init.ets + import { initHandler } from "./handler"; + + class Foo { + bar: string = ""; + } + + export function init() { + let foo = new Foo(); + foo.bar = "this is bar property"; + initHandler(foo); + } + +.. code-block:: typescript + :linenos: + + // arkts 2.0 file + import { init } from "./init"; + import { getHandler } from "./handler"; + + init(); + let handler = getHandler(); // how to handle the closure's lifetime??????? + + handler(); Object of primitive types (empty) ********************************* @@ -985,21 +1185,49 @@ Object of primitive types (empty) Description ^^^^^^^^^^^ -- Null +The primitive types in JavaScript have no methods or properties. +When accessing a property or method, the primitive value is wrapped into an Object(aka auto-boxing). +And actually the method or property is called on the object, not on the primitive value. + +.. code-block:: javascript + :linenos: -- Undefined + let str = "string literal"; -- Boolean + // Actually, variable str is auto-boxed into an String Object. + // Then String.toUpperCase() is called. + console.log(str.toUpperCase()); -- Number +The converting rules are: -- Bigint +- null -> Null +- undefined -> Undefined +- boolean -> Boolean +- number -> Number +- bigint -> Bigint +- string -> String +- symbol-> Symbol -- String +Interop rules +^^^^^^^^^^^^^ -- Symbol +- If a primitive type is passed from ArkTS2.0 to JS world, the primitive type will follow the auto-boxing rules. - Symbol is a unique and immutable data type that can be used as an identifier for object properties. +.. code-block:: javascript + :linenos: + + // file1.js + export function toUpperCase(str) { + return str.toUpperCase(); // the string will be auto-boxed into an String Object + } + +.. code-block:: typescript + :linenos: + + // file2.ets ArkTS2.0 + import { toUpperCase } from './file1' + + let res = toUpperCase("string literal"); // string type in arkts 2.0 will be converted to string type in JS world The ``typeof`` Operator (empty) @@ -1008,7 +1236,8 @@ The ``typeof`` Operator (empty) Description ^^^^^^^^^^^ -The ``typeof`` operator returns a string indicating the type of the operand's value. +The ``typeof`` operator returns a string indicating the type of the operand's value. +The rules are: +-------------------------------------------------------------------------------+-----------+ | Type | Result | @@ -1034,6 +1263,15 @@ The ``typeof`` operator returns a string indicating the type of the operand's va |Any other object | "object" | +-------------------------------------------------------------------------------+-----------+ +.. code-block:: javascript + :linenos: + + let foo = "bar"; + console.log(typeof foo); // string + +Interop rules +^^^^^^^^^^^^^ +- When the operand is from ArkTS2.0, if the operand's type converted to JS must is primitive, the operator returns the primitive's type name as above. Otherwise, the operator returns "object". Generators (empty) ****************** @@ -1051,6 +1289,12 @@ Generators can return (``yield``) multiple values, one after another, on-demand. - ``generator.return()``: returns a value and terminates the generator - ``generator.throw()``: throws an error and terminates the generator +Interop rules +^^^^^^^^^^^^^ + +- ``Generator`` are not supported by ArkTS standard library. + + ``With`` statement (empty) ************************** @@ -1060,17 +1304,33 @@ Description Use of the ``with`` statement is not recommended, as it may be the source of confusing bugs and compatibility issues, makes optimization impossible, and is forbidden in ``strict mode``. The recommended alternative is to assign the object whose properties you want to access to a temporary variable. +This feature is deprecated, using it may cause problems. + +Interop rules +^^^^^^^^^^^^^ + +- This feature is deprecated, do not use it. + The ``debugger`` statement (empty) ********************************** - Description ^^^^^^^^^^^ The ``debugger`` statement invokes any available debugging functionality, such as setting a breakpoint. If no debugging functionality is available, this statement has no effect. +.. code-block:: javascript + + :linenos: + // dummy code + dubugger; // interrupt when debugging + +Interop rules +^^^^^^^^^^^^^ +- This statement has not interop with ArkTS2.0. + Proxies (empty) *************** @@ -1103,6 +1363,11 @@ You create a ``Proxy`` with two parameters: console.log(proxy2.message1); // world console.log(proxy2.message2); // world +Interop rules +^^^^^^^^^^^^^ + +- ``Proxy`` are not supported by ArkTS standard library. + The Global Object (empty) ************************* @@ -1133,6 +1398,10 @@ Other properties of the ``Global Object``: - Reflect +Interop rules +^^^^^^^^^^^^^ +- This feature has not interop with ArkTS2.0. + Reflect (empty) *************** @@ -1156,11 +1425,30 @@ The ``Reflect`` object has a number of methods that allow developers to access a ``Reflect.get()``, ``Reflect.set()``, ``Reflect.apply()``, ``Reflect.construct()`` methods +Interop rules +^^^^^^^^^^^^^ +- For now, this feature has not be supported to interop with ArkTS2.0. If try to reflected an Proxy object from ArkTS2.0 in JS world, the runtime will throw an error. + .. _JS Std library: Symbol (empty) ************** +Description +^^^^^^^^^^^ + +Symbol is a primitive in JS which stand for a unique symbol(aka symbol value). + +.. code-block:: javascript + + let s = Symbol("foo"); + console.log(typeof s); // symbol + +Interop rules +^^^^^^^^^^^^^ + +- Primitive type ``symbol`` and Object ``Symbol`` are not supported by ArkTS standard library. + JS Std library ############## @@ -1170,6 +1458,8 @@ Arrays Description ^^^^^^^^^^^ +The Array Object in JavaScript replasents a collection of some elements. The elements can be of different types. + Interop rules ^^^^^^^^^^^^^ @@ -1180,8 +1470,7 @@ Interop rules :linenos: //file1.js - let a new ; - export let a = new Array(1, 2, 3, 4, 5); + export let a = new Array(1, 2, 3, 4, 5); export let b = [1, 2, 3, 4 ,5] .. code-block:: typescript @@ -1206,6 +1495,38 @@ Map (empty) ArrayBuffer (empty) ******************* +ArrayBuffer stands for byte buffer in JavaScript. ArrayBuffer cannot be directly manipulated. Instead, it's needed to create `TypedArray` or `DataView` to write or read the buffer. + +.. code-block:: javascript + :linenos: + + // file1.js + let buf = new ArrayBuffer(128); + let bytebuf = new Uint8Array(buf); + + // manipulate bytebuf + // ... + +Interop rules +^^^^^^^^^^^^^ +- ``ArrayBuffer`` in ArkTS2.0 is an JS API-compatible object, so it can be passed through interop to ArkTS2.0. Therefore, an ArrayBuffer Object in JavaScript be casted to ab ArrayBuffer object in ArkTS2.0. + +.. code-block:: javascript + :linenos: + + //file1.js + export let buf = new ArrayBuffer(128); + +.. code-block:: typescript + :linenos: + + // file2.ets ArkTS2.0 + + import {buf} from 'file1' + + let array_buffer = buf as ArrayBuffer; // use as operator to casted it. + let int8_array = new Int8Array(buf); // consturctor(array: ArrayLike | ArrayBuffer); // casted to Int8Array if needed. + BigInt64Array (empty) ^^^^^^^^^^^^^^^^^^^^^ @@ -1242,6 +1563,54 @@ Uint32Array (empty) DataView (empty) **************** +DataView is used to read and write byte buffer. + +.. code-block:: javascript + :linenos: + + // 00 00 00 00 00 00 00 00 + let buf = new ArrayBuffer(8); + let view = new DataView(buf); + + // 00 01 00 00 00 00 00 00 + view.setInt16(0, 1); + + // read as big-endian + // 00 01 00 00 00 00 00 00 + // ^~~~~~~~~~^ + // |--Int32--| High --- Low + console.log(view.getInt32(0)); + + // read as little-endian + // 00 01 00 00 00 00 00 00 + // ^~~~~~~~~~^ + // |--Int32--| Low --- High + console.log(view.getInt32(0, true)); // 256 + +Interop rules +^^^^^^^^^^^^^ + +- ``DataView`` can be passed through interop to ArkTS2.0. An DataView Object in Javascript be casted to an DataView object in ArkTS2.0. + +.. code-block:: javascript + :linenos: + + //file1.js + export let buf = new ArrayBuffer(128); + export let view = new DataView(buf); + +.. code-block:: typescript + :linenos: + + // file2.ets ArkTS2.0 + + import {view} from 'file1' + + console.log(view.getInt32(0, true) as int); // use as ESObject. + + let data_view = view as DataView; // use as operator to casted it. + console.log(data_view.getInt32(0, true)); + Date (empty) ************ diff --git a/static_core/plugins/ets/doc/interop_js/6_ts.rst b/static_core/plugins/ets/doc/interop_js/6_ts.rst index cd24beb8314d4666d979411fd100fa0dbaab0401..41a5f10db9f4e14c9a1f7c541b230eff3fcce087 100644 --- a/static_core/plugins/ets/doc/interop_js/6_ts.rst +++ b/static_core/plugins/ets/doc/interop_js/6_ts.rst @@ -97,26 +97,229 @@ https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#less-common-p Narrowing (empty) ***************** +Description +=========== + +Narrowing can be used to narrow the type of a variable in a conditional block. + +.. code-block:: typescript + :linenos: + + function foo(bar: number | string) { + if(typeof(bar) == "number"){ + console.log(bar.toFixed(2)); // asumeing that bar is number type + } else { + console.log(bar.charAt(0)); // asumeing that bar is string type + } + } + +Interop rules +============= + +- Narrowing is just a feature for type checking. It is safe to use it with ArkTS2.0's type. + +.. code-block:: typescript + :linenos: + + // file1.ets + export class Foo { + bar: int; + } + +.. code-block:: typescript + :linenos: + + // file2.ts + import { Foo } from 'file1'; + function foo(bar: number | Foo) { + if(typeof(bar) == "number"){ + console.log(bar.toFixed(2)); // asumeing that bar is number type + } else { + console.log(bar.bar); // asumeing that bar is Foo type + } + } + https://www.typescriptlang.org/docs/handbook/2/narrowing.html Function Type Expressions ************************* +Description +=========== + +- A function type expression describes a function type, with it's parameters and return type. + +.. code-block:: typescript + :linenos: + + // (x: number) => number is a function type expression, + // it describes a function that takes an int and returns an int + function foo(f: (x: number) => number): number { + return f(1) + 123; + } + +Interop rules +============= + +- A function type described by a function type expression in TypeScript can be auto converted to a function type when interoping with ArkTS2.0. +- Limitation: The types of the parameters and return value of the function type expression must be able to be casted to an ArkTS2.0 type. + +.. code-block:: typescript + :linenos: + + // file1.ets + export function func_good(f: (x: number) => number): number { + return f(1) + 123; + } + + export function func_bad1(f: (x: any) => number): number { + return f(1) + 123; + } + + export function func_bad2(f: (x: symbol) => number): number { + return f(Symbol("bar")) + 123; + } + +.. code-block:: typescript + :linenos: + + // file2.ts + import { func_good, func_bad1, func_bad2 } from 'file1'; + func_good((x: number) => x); // OK, (x: number) => number is casted to (x: number) => number + func_bad1((x: number) => x); // compile time error, any cannot be casted to an ArkTS2.0 type + func_bad2((x: number) => x); // compile time error, symbol cannot be casted to an ArkTS2.0 type + + https://www.typescriptlang.org/docs/handbook/2/functions.html#function-type-expressions Call Signatures (empty) *********************** +Description +=========== + +- A call signature describes a callable function with properties. + +.. code-block:: typescript + :linenos: + + type LogHandler = { + name_str: string; + (content: string): void; + } + + function log(content: string, handler: LogHandler) { + console.log("use handler: {handler.name}"); + handler(content); + } + + function log_handler(content: string) { + console.log(content); + } + + log_handler.name_str = "log handler"; + log("log test", log_handler); + +Interop rules +============= + +- Call signatures are not supported by ArkTS2.0. Any interop with call signatures would causes compile time error. + +.. code-block:: typescript + :linenos: + + // file1.ets + export type LogHandler = { + name_str: string; + (content: string): void; + } + + export function log(content: string, handler: LogHandler) { + console.log("use handler: {handler.name}"); + handler(content); + } + + export function log_handler(content: string) { + console.log(content); + } + + log_handler.name_str = "log handler"; + + +.. code-block:: typescript + :linenos: + + // file2.ets + import { log, log_handler } from 'file1'; + log("log test", log_handler); // compile time error + https://www.typescriptlang.org/docs/handbook/2/functions.html#call-signatures Construct Signatures (empty) **************************** +Description +=========== + +- A construct signature describes a callable function which can be call by ``new`` operator. + +.. code-block:: typescript + :linenos: + + class Foo { + bar: number = 0; + + constructor(bar: number) { + this.bar = bar; + } + } + + type Constructor = { + new (bar: number): Foo; + } + + let MyFooConstructor: Constructor = Foo; + let foo = new MyFooConstructor(123); + console.log(foo.bar); // 123 + +Interop rules +============= + +- Construct signatures are not supported by ArkTS2.0. Any interop with construct signatures would causes compile time error. + +.. code-block:: typescript + :linenos: + + // file1.ets + class Foo { + bar: number = 0; + + constructor(bar: number) { + this.bar = bar; + } + } + + type Constructor = { + new (bar: number): Foo; + } + + export let MyFooConstructor: Constructor = Foo; + +.. code-block:: typescript + :linenos: + + // file2.ets + import { MyFooConstructor } from 'file1'; + + let foo = new MyFooConstructor(123); // compile time error + https://www.typescriptlang.org/docs/handbook/2/functions.html#construct-signatures Generic Functions (empty) ************************* + + https://www.typescriptlang.org/docs/handbook/2/functions.html#construct-signatures Optional Parameters (empty) @@ -510,6 +713,17 @@ https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html Symbols (empty) *************** +Description +=========== + +Symbol is a primitive date type which stand for a unique symbol(aka symbol value). + +.. code-block:: typescript + :linenos: + + let sym = Symbol(); + console.log(typeof(sym)); // symbol + https://www.typescriptlang.org/docs/handbook/symbols.html - Symbol.asyncIterator @@ -525,6 +739,24 @@ https://www.typescriptlang.org/docs/handbook/symbols.html - Symbol.toStringTag - Symbol.unscopables +Interop rules +============= + +- Primitive type ``symbol`` and Object ``Symbol`` are not supported by ArkTS standard library. Any interop with these types would causes compile time error. + +.. code-block:: typescript + :linenos: + + // file1.ts + export let sym = Symbol(); + +.. code-block:: typescript + :linenos: + + // file2.ets + import { sym } from 'file1'; + console.log(sym); // compile time error + Triple-Slash Directives (empty) ******************************* diff --git a/static_core/plugins/ets/doc/interop_js/index.rst b/static_core/plugins/ets/doc/interop_js/index.rst index 0a12bf57e82aac7c51fbfd262f826e167bf95c71..08de086264db740efc6858c6776261ac1789a546 100644 --- a/static_core/plugins/ets/doc/interop_js/index.rst +++ b/static_core/plugins/ets/doc/interop_js/index.rst @@ -19,11 +19,9 @@ :maxdepth: 3 /1_introduction - /2_esobject /3_conversions_type_check /4_conversions_runtime /5_js /6_ts /7_arkts /99_backlog_features_recheck -