[M85 Migration] Add an evas gl option for rotation
[platform/framework/web/chromium-efl.git] / docs / closure_compilation.md
1 # Closure Compilation
2
3 ## What is type safety?
4
5 [Strongly-typed languages](https://en.wikipedia.org/wiki/Strong_and_weak_typing)
6 like C++ and Java have the notion of variable types.
7
8 This is typically baked into how you declare variables:
9
10 ```c++
11 const int32 kUniversalAnswer = 42;  // type = 32-bit integer
12 ```
13
14 or as [templates](https://en.wikipedia.org/wiki/Template_metaprogramming) for
15 containers or generics:
16
17 ```c++
18 std::vector<int64> fibonacci_numbers;  // a vector of 64-bit integers
19 ```
20
21 When differently-typed variables interact with each other, the compiler can warn
22 you if there's no sane default action to take.
23
24 Typing can also be manually annotated via mechanisms like `dynamic_cast` and
25 `static_cast` or older C-style casts (i.e. `(Type)`).
26
27 Using stongly-typed languages provide _some_ level of protection against
28 accidentally using variables in the wrong context.
29
30 JavaScript is weakly-typed and doesn't offer this safety by default. This makes
31 writing JavaScript more error prone, and various type errors have resulted in
32 real bugs seen by many users.
33
34 ## Chrome's solution to typechecking JavaScript
35
36 Enter [Closure Compiler](https://developers.google.com/closure/compiler/), a
37 tool for analyzing JavaScript and checking for syntax errors, variable
38 references, and other common JavaScript pitfalls.
39
40 To get the fullest type safety possible, it's often required to annotate your
41 JavaScript explicitly with [Closure-flavored @jsdoc
42 tags](https://developers.google.com/closure/compiler/docs/js-for-compiler)
43
44 ```js
45 /**
46  * @param {string} version A software version number (i.e. "50.0.2661.94").
47  * @return {!Array<number>} Numbers corresponding to |version| (i.e. [50, 0, 2661, 94]).
48  */
49 function versionSplit(version) {
50   return version.split('.').map(Number);
51 }
52 ```
53
54 See also:
55 [the design doc](https://docs.google.com/a/chromium.org/document/d/1Ee9ggmp6U-lM-w9WmxN5cSLkK9B5YAq14939Woo-JY0/edit).
56
57 ## Typechecking Your Javascript
58
59 Given an example file structure of:
60
61   + lib/does_the_hard_stuff.js
62   + ui/makes_things_pretty.js
63
64 `lib/does_the_hard_stuff.js`:
65
66 ```javascript
67 var wit = 100;
68
69 // ... later on, sneakily ...
70
71 wit += ' IQ';  // '100 IQ'
72 ```
73
74 `ui/makes_things_pretty.js`:
75
76 ```javascript
77 /** @type {number} */ var mensa = wit + 50;
78
79 alert(mensa);  // '100 IQ50' instead of 150
80 ```
81
82 Closure compiler can notify us if we're using `string`s and `number`s in
83 dangerous ways.
84
85 To do this, we can create:
86
87   + ui/BUILD.gn
88
89 With these contents:
90
91 ```
92 # Copyright 2018 The Chromium Authors. All rights reserved.
93 # Use of this source code is governed by a BSD-style license that can be
94 # found in the LICENSE file.
95
96 import("//third_party/closure_compiler/compile_js.gni")
97
98 js_type_check("closure_compile") {
99   deps = [
100     ":make_things_pretty",
101   ]
102 }
103
104 js_library("make_things_pretty") {
105   deps = [
106     "../lib:does_the_hard_stuff",
107   ]
108
109   externs_list = [
110     "$externs_path/extern_name_goes_here.js"
111   ]
112 }
113 ```
114
115 ## Running Closure compiler locally
116
117 You can locally test that your code compiles on Linux or Mac.  This requires
118 [Java](http://www.oracle.com/technetwork/java/javase/downloads/index.html) and a
119 [Chrome checkout](https://www.chromium.org/developers/how-tos/get-the-code) (i.e.
120 python, depot_tools). Note: on Ubuntu, you can probably just run `sudo apt-get
121 install openjdk-7-jre`.
122
123 After you set closure_compile = true in your gn args, you should be able to run:
124
125 ```shell
126 ninja -C out/Default webui_closure_compile
127 ```
128
129 and should see output like this:
130
131 ```shell
132 ninja: Entering directory `out/Default/'
133 [0/1] ACTION Compiling ui/makes_things_pretty.js
134 ```
135
136 To compile only a specific folder, add an argument after the script name:
137
138 ```shell
139 ninja -C out/Default ui:closure_compile
140 ```
141
142 In our example code, this error should appear:
143
144 ```
145 (ERROR) Error in: ui/makes_things_pretty.js
146 ## /my/home/chromium/src/ui/makes_things_pretty.js:1: ERROR - initializing variable
147 ## found   : string
148 ## required: number
149 ## /** @type {number} */ var mensa = wit + 50;
150 ##                                   ^
151 ```
152
153 Hooray! We can catch type errors in JavaScript!
154
155 ## Preferred BUILD.gn structure
156 * Make all individual JS file targets a js\_library.
157 * The top level target should be called “closure\_compile”.
158 * If you have subfolders that need compiling, make “closure\_compile” a group(),
159   and any files in the current directory a js\_type\_check() called “<directory>\_resources”.
160 * Otherwise, just make “closure\_compile” a js\_type\_check with all your js\_library targets as deps
161 * Leave all closure targets below other kinds of targets becaure they’re less ‘important’
162
163 See also:
164 [Closure Compilation with GN](https://docs.google.com/a/chromium.org/document/d/1Ee9ggmp6U-lM-w9WmxN5cSLkK9B5YAq14939Woo-JY0/edit).
165
166 ## Trying your change
167
168 Closure compilation runs in the compile step of Linux, Android and ChromeOS builds.
169
170 From the command line, you try your change with:
171
172 ```shell
173 git cl try -b linux-rel
174 ```
175
176 ## Integrating with the continuous build
177
178 To compile your code on every commit, add your file to the
179 `'webui_closure_compile'` target in `src/BUILD.gn`:
180
181 ```
182   group("webui_closure_compile") {
183     data_deps = [
184       # Other projects
185       "my/project:closure_compile",
186     ]
187   }
188 ```
189
190 ## Externs
191
192 [Externs files](https://github.com/google/closure-compiler/wiki/FAQ#how-do-i-write-an-externs-file)
193 define APIs external to your JavaScript. They provide the compiler with the type
194 information needed to check usage of these APIs in your JavaScript, much like
195 forward declarations do in C++.
196
197 Third-party libraries like Polymer often provide externs. Chrome must also
198 provide externs for its extension APIs. Whenever an extension API's `idl` or
199 `json` schema is updated in Chrome, the corresponding externs file must be
200 regenerated:
201
202 ```shell
203 ./tools/json_schema_compiler/compiler.py -g externs \
204   extensions/common/api/your_api_here.idl \
205   > third_party/closure_compiler/externs/your_api_here.js
206 ```