If we detect a change in an inline function `foo` with @JvmName
`fooJvmName`, we have two options:
1. Report that function `foo` has changed
2. Report that method `fooJvmName` has changed
Similarly, if we detect a change in an inline property accessor with
JvmName `getFoo` of property `foo`, we have two options:
1. Report that property `foo` has changed
2. Report that property accessor `getFoo` has changed
The compiler is guaranteed to generate `LookupSymbol`s corresponding to
option 1 when referencing inline functions/property accessors, but it is
not guaranteed to generate `LookupSymbol`s corresponding to option 2.
(Currently the compiler seems to support option 2 for *inline*
functions/property accessors, but that may change.)
Therefore, we will choose option 1 as it is cleaner and safer.
^KT-54144 In progress
Small cleanup in IncrementalCompilerRunner
- Add comment for closing caches
- Rename providedChangedFiles to changedFiles
- Tiny clean up in `performWorkBeforeCompilation`
- Count directories to delete in debug logs
^KT-53015 In progress
Extract KotlinClassInfo to a separate class
to reduce the size of IncrementalJvmCache and prepare for the next
change.
^KT-54144 In progress
Ignore inline functions that are not found in the bytecode
^KT-54144 In progress
Add unit test for handling `@JvmName`s
Test: KotlinOnlyClasspathChangesComputerTest
#testFunctionsAndPropertyAccessorsWithJvmNames
^KT-54144 Fixed
Update unit tests for handling `@JvmName`s
In a previous commit, we made a behavior change for inline property
accessors: The existing behavior is that if the implementation of an
inline getter has changed, only usages of the getter will be impacted
but not usages of the setter (and vice versa).
After that previous commit, usages of *both* the getter and setter will
now be impacted (i.e., we might compile slightly more files). This is
because a change to either the getter or the setter will now be
considered a change to the property, which will help simplify our change
analysis.
This commit updates the relevant unit tests to reflect the new behavior.
Test: Updated Incremental*TestGenerated.PureKotlin#testInlinePropertyInClass
and Incremental*TestGenerated.PureKotlin#testInlinePropertyOnTopLevel
^KT-54144 Fixed
JavaScript Translation
This module performs the translation of Kotlin source code to JavaScript.
There are various Kotlin APIs to JavaScript environments in the standard library.
Compiling the Kotlin Standard Library for JavaScript
The Kotlin Standard Library for JS is built with gradle, see the corresponding module's ReadMe.
Reusing JVM based test cases in JavaScript
Any Kotlin test cases using the org.junit.Test annotation and the kotlin.test package, such as this test case are automatically converted to JavaScript using QUnit.
This allows the test cases to be run directly in a web page in any web browser.
Using the Kotlin Library in JavaScript
There is a simple sample which shows how to use the Kotlin Standard Library from inside JavaScript in a web page.
Contributing
We love contributions! The JavaScript translation could really use your help! If you fancy contributing:
- check the contributing section on general stuff like getting the code etc
- try fix one of the pending JavaScript translation issues
Testing the Kotlin/JS compiler
The following Gradle tasks are responsible for testing the Kotlin/JS compiler:
:js:js.tests:jsIrTest— run JS tests against the IR backend, plus the same tests with dead code elimination (DCE) enabled.:js:js.tests:jsTest— run JS tests against the legacy backend, plus the same tests with DCE enabled.:js:js.tests:quickTest— run JS tests against the legacy backend. No DCE.:js:js.tests:test— run all JS tests, against both the legacy and the IR backends, plus the same tests with DCE enabled.
The JavaScript files generated from the test files are located in the following directories, divided by the translation mode:
js/js.tests/build/out— JS files generated with theFULLtranslation mode (all modules are compiled into one big JS file)js/js.tests/build/out-min— the same as previous, but with DCE applied.js/js.tests/build/out-per-module— JS files generated with thePER_MODULEtranslation mode (each module is compiled into a separate JS file)js/js.tests/build/out-per-module-min— the same as previous, but with DCE applied.
There are multiple kinds of tests. Here are some of them:
- Box tests. Those are the tests that we are often most interested in, they are located in
js/js.translator/testData/box. Such tests must contain afn box(): Stringfunction. If this function returns"OK", the test is considered passed, and if it returns anything else, the test is considered failed. - Line number tests, located in
js/js.translator/testData/lineNumbers. These are to ensure that the debug info in the generated JavaScript matches some expectation. The expectation is written in a comment staring with// LINES(JS):or// LINES(JS_IR):. These comments contain a list of line numbers in the test file that the compiler output is generated from. The actual line numbers can be viewed in the generated JS file whose name ends with-lines.js. - TypeScript export tests, located in
js/js.translator/testData/typescript-export. These test that the generated.d.ts(TypeScript definitions) file matches the reference.d.tsfile. - Also, some tests located in
compiler/testData/codegenare shared between the JS and the JVM backends.
Manually running the generated JS files (IR backend only)
There is a helpful tool for running and debugging JS code generated from test files right in Intellij IDEA.
Note that this will only work for files generated with the IR backend in the FULL translation mode,
because these files are self-sufficient and don't require any dependencies.
Just open a generated JS file located in js/js.tests/build/out, select
the "run IR test in node.js" run configuration in IDEA, and click on the "Run" or "Debug" icon.
The test output will be printed in the console.
Bonus: debugging is supported! You can set a breakpoint in a test file, open the generated JS file, select the "run IR test in node.js" run configuration and click on the "Debug" icon. The execution should pause and the breakpoint will be hit. This works because a source map located next to the generated JS file.