Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Unified Diff: docs/closure_compilation.md

Issue 1942133002: Closure compilation: rewrite doc now that there's try bots (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: change order of try and continous integration systems Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: docs/closure_compilation.md
diff --git a/docs/closure_compilation.md b/docs/closure_compilation.md
index bc1cabd3c5d673f3950c21dbd4f2e1237aeb4f76..5ba5e05e293cff7c2b97332da13f173b3fb1d34c 100644
--- a/docs/closure_compilation.md
+++ b/docs/closure_compilation.md
@@ -1,73 +1,67 @@
# Closure Compilation
-## I just need to fix the compile!
+## What is type safety?
-### Pre-requisites
+[Strongly-typed languages](https://en.wikipedia.org/wiki/Strong_and_weak_typing)
+like C++ and Java have the notion of variable types.
-You'll need Java 7 (preferably the OpenJDK version). To install on Ubuntu:
+This is typically baked into how you declare variables:
-```shell
-sudo apt-get install openjdk-7-jre
+```c++
+const int32 kUniversalAnswer = 42; // type = 32-bit integer
```
-On Mac or Windows, visit:
-[http://www.oracle.com/technetwork/java/javase/downloads/index.html](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
-
-### Using ninja to compile the code
-
-To compile the JavaScript, run this script:
+or as [templates](https://en.wikipedia.org/wiki/Template_metaprogramming) for
+containers or generics:
-```shell
-third_party/closure_compiler/run_compiler
+```c++
+std::vector<int64> fibonacci_numbers; // a vector of 64-bit integers
```
-The output should look something like this:
+When differently-typed variables interact with each other, the compiler can warn
+you if there's no sane default action to take.
-```shell
-ninja: Entering directory `out/Default/'
-[30/106] ACTION Compiling chrome/browser/resources/md_history/constants.js
-```
+Typing can also be manually annotated via mechanisms like `dynamic_cast` and
+`static_cast` or older C-style casts (i.e. `(Type)`).
-To compile only a specific target, add an argument after the script name:
+Using stongly-typed languages provide _some_ level of protection against
+accidentally using variables in the wrong context.
-```shell
-third_party/closure_compiler/run_compiler people_page
-```
+JavaScript is weakly-typed and doesn't offer this safety by default. This makes
+writing JavaScript more error prone, and various type errors have resulted in
+real bugs seen by many users.
+
+## Chrome's solution to typechecking JavaScript
-## Background
+Enter [Closure Compiler](https://developers.google.com/closure/compiler/), a
+tool for analyzing JavaScript and checking for syntax errors, variable
+references, and other common JavaScript pitfalls.
-In C++ and Java, compiling the code gives you _some_ level of protection against
-misusing variables based on their type information. JavaScript is loosely typed
-and therefore doesn't offer this safety. This makes writing JavaScript more
-error prone as it's _one more thing_ to mess up.
+To get the fullest type safety possible, it's often required to annotate your
+JavaScript explicitly with [Closure-flavored @jsdoc
+tags](https://developers.google.com/closure/compiler/docs/js-for-compiler)
-Because having this safety is handy, Chrome now has a way to optionally
-typecheck your JavaScript and produce compiled output with
-[Closure Compiler](https://developers.google.com/closure/compiler/).
-The type information is
-[annotated in comment tags](https://developers.google.com/closure/compiler/docs/js-for-compiler)
-that are briefly described below.
+```js
+/**
+ * @param {string} version A software version number (i.e. "50.0.2661.94").
+ * @return {!Array<number>} Numbers corresponing to |version| (i.e. [50, 0, 2661, 94]).
+ */
+function versionSplit(version) {
+ return version.split('.').map(Number);
+}
+```
See also:
[the design doc](https://docs.google.com/a/chromium.org/document/d/1Ee9ggmp6U-lM-w9WmxN5cSLkK9B5YAq14939Woo-JY0/edit).
-## Assumptions
-
-A working Chrome checkout. See here:
-https://www.chromium.org/developers/how-tos/get-the-code
-
## Typechecking Your Javascript
-So you'd like to compile your JavaScript!
-
-Maybe you're working on a page that looks like this:
+Given an example file structure of:
-```html
-<script src="other_file.js"></script>
-<script src="my_product/my_file.js"></script>
-```
+ + lib/does_the_hard_stuff.js
+ + ui/makes_things_pretty.js
-Where `other_file.js` contains:
+`lib/does_the_hard_stuff.js`:
```javascript
var wit = 100;
@@ -77,18 +71,22 @@ var wit = 100;
wit += ' IQ'; // '100 IQ'
```
-and `src/my_product/my_file.js` contains:
+`ui/makes_things_pretty.js`:
```javascript
/** @type {number} */ var mensa = wit + 50;
+
alert(mensa); // '100 IQ50' instead of 150
```
-In order to check that our code acts as we'd expect, we can create a
+Closure compiler can notify us if we're using `string`s and `number`s in
+dangerous ways.
+
+To do this, we can create:
- my_project/compiled_resources2.gyp
+ + ui/compiled_resources2.gyp
-with the contents:
+With these contents:
```
# Copyright 2016 The Chromium Authors. All rights reserved.
@@ -97,203 +95,104 @@ with the contents:
{
'targets': [
{
- 'target_name': 'my_file', # file name without ".js"
- 'dependencies': [ # No need to specify empty lists.
- '../compiled_resources2.gyp:other_file',
- '<(EXTERNS_GYP):any_needed_externs' # e.g. chrome.send(), chrome.app.window, etc.
+ # Target names is typically just without ".js"
+ 'target_name': 'makes_things_pretty',
+
+ 'dependencies': [
+ '../lib/compiled_resources2.gyp:does_the_hard_stuff',
+
+ # Teaches closure about non-standard environments/APIs, e.g.
+ # chrome.send(), chrome.app.window, etc.
+ '<(EXTERNS_GYP):extern_name_goes_here'
],
- 'includes': ['../third_party/closure_compiler/compile_js2.gypi'],
+
+ 'includes': ['../path/to/third_party/closure_compiler/compile_js2.gypi'],
},
],
}
```
-You should get results like:
+## Running Closure compiler locally
-```
-(ERROR) Error in: my_project/my_file.js
-## /my/home/chromium/src/my_project/my_file.js:1: ERROR - initializing variable
-## found : string
-## required: number
-## /** @type {number} */ var mensa = wit + 50;
-## ^
-```
+You can locally test that your code compiles on Linux or Mac. This requires
+[Java](http://www.oracle.com/technetwork/java/javase/downloads/index.html) and a
+[Chrome checkout](http://www.chromium.org/developers/how-tos/get-the-code) (i.e.
+python, depot_tools). Note: on Ubuntu, you can probably just run `sudo apt-get
+install openjdk-7-jre`.
-Yay! We can easily find our unexpected type errors and write less error-prone
-code!
+Now you should be able to run:
-## Continuous Checking
-
-To compile your code on every commit, add a line to
-/third_party/closure_compiler/compiled_resources.gyp
-like this:
-
-```
-{
- 'targets': [
- {
- 'target_name': 'compile_all_resources',
- 'dependencies': [
- # ... other projects ...
-++ '../my_project/compiled_resources2.gyp:*',
- ],
- }
- ]
-}
+```shell
+third_party/closure_compiler/run_compiler
```
-and the
-[Closure compiler bot](http://build.chromium.org/p/chromium.fyi/builders/Closure%20Compilation%20Linux)
-will [re-]compile your code whenever relevant .js files change.
-
-## Using Compiled JavaScript
+and should see output like this:
-Compiled JavaScript is output in
-`src/out/<Debug|Release>/gen/closure/my_project/my_file.js` along with a source
-map for use in debugging. In order to use the compiled JavaScript, we can create
-a
-
- my_project/my_project_resources.gyp
-
-with the contents:
-
-```
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'targets': [
- {
- # GN version: //my_project/resources
- 'target_name': 'my_project_resources',
- 'type': 'none',
- 'variables': {
- 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/my_project',
- 'my_file_gen_js': '<(SHARED_INTERMEDIATE_DIR)/closure/my_project/my_file.js',
- },
- 'actions': [
- {
- # GN version: //my_project/resources:my_project_resources
- 'action_name': 'generate_my_project_resources',
- 'variables': {
- 'grit_grd_file': 'resources/my_project_resources.grd',
- 'grit_additional_defines': [
- '-E', 'my_file_gen_js=<(my_file_gen_js)',
- ],
- },
- 'includes': [ '../build/grit_action.gypi' ],
- },
- ],
- 'includes': [ '../build/grit_target.gypi' ],
- },
- ],
-}
+```shell
+ninja: Entering directory `out/Default/'
+[0/1] ACTION Compiling ui/makes_things_pretty.js
```
-The variables can also be defined in an existing .gyp file if appropriate. The
-variables can then be used in to create a
-
- my_project/my_project_resources.grd
-
-with the contents:
+To compile only a specific target, add an argument after the script name:
-```
-<?xml version="1.0" encoding="utf-8"?>
-<grit-part>
- <include name="IDR_MY_FILE_GEN_JS" file="${my_file_gen_js}" use_base_dir="false" type="BINDATA" />
-</grit-part>
+```shell
+third_party/closure_compiler/run_compiler makes_things_pretty
```
-In your C++, the resource can be retrieved like this:
+In our example code, this error should appear:
```
-base::string16 my_script =
- base::UTF8ToUTF16(
- ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_MY_FILE_GEN_JS)
- .as_string());
+(ERROR) Error in: ui/makes_things_pretty.js
+## /my/home/chromium/src/ui/makes_things_pretty.js:1: ERROR - initializing variable
+## found : string
+## required: number
+## /** @type {number} */ var mensa = wit + 50;
+## ^
```
-## Debugging Compiled JavaScript
+Hooray! We can catch type errors in JavaScript!
-Along with the compiled JavaScript, a source map is created:
-`src/out/<Debug|Release>/gen/closure/my_project/my_file.js.map`
+## Trying your change
-Chrome DevTools has built in support for working with source maps:
-https://developer.chrome.com/devtools/docs/javascript-debugging#source-maps
+Closure compilation also has [try
+bots](https://build.chromium.org/p/tryserver.chromium.linux/builders/closure_compilation)
+which can check whether you could *would* break the build if it was committed.
-In order to use the source map, you must first manually edit the path to the
-'sources' in the .js.map file that was generated. For example, if the source map
-looks like this:
+From the command line, you try your change with:
-```
-{
-"version":3,
-"file":"/tmp/gen/test_script.js",
-"lineCount":1,
-"mappings":"A,aAAA,IAAIA,OAASA,QAAQ,EAAG,CACtBC,KAAA,CAAM,OAAN,CADsB;",
-"sources":["/tmp/tmp70_QUi"],
-"names":["fooBar","alert"]
-}
+```shell
+git cl try -b closure_compilation
```
-sources should be changed to:
+To automatically check that your code typechecks cleanly before submitting, you
+can add this line to your CL description:
```
-...
-"sources":["/tmp/test_script.js"],
-...
+CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:closure_compilation
```
-In your browser, the source map can be loaded through the Chrome DevTools
-context menu that appears when you right click in the compiled JavaScript source
-body. A dialog will pop up prompting you for the path to the source map file.
-Once the source map is loaded, the uncompiled version of the JavaScript will
-appear in the Sources panel on the left. You can set break points in the
-uncompiled version to help debug; behind the scenes Chrome will still be running
-the compiled version of the JavaScript.
-
-## Additional Arguments
+Working in common resource directories in Chrome automatically adds this line
+for you.
-`compile_js.gypi` accepts an optional `script_args` variable, which passes
-additional arguments to `compile.py`, as well as an optional `closure_args`
-variable, which passes additional arguments to the closure compiler. You may
-also override the `disabled_closure_args` for more strict compilation.
+## Integrating with the continuous build
-For example, if you would like to specify multiple sources, strict compilation,
-and an output wrapper, you would create a
+To compile your code on every commit, add your file to the `'dependencies'` list
+in `src/third_party/closure_compiler/compiled_resources2.gyp`:
```
-my_project/compiled_resources.gyp
-```
-
-with contents similar to this:
-
-```
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
{
- 'targets' :[
+ 'targets': [
{
- 'target_name': 'my_file',
- 'variables': {
- 'source_files': [
- 'my_file.js',
- 'my_file2.js',
- ],
- 'script_args': ['--no-single-file'], # required to process multiple files at once
- 'closure_args': [
- 'output_wrapper=\'(function(){%output%})();\'',
- 'jscomp_error=reportUnknownTypes', # the following three provide more strict compilation
- 'jscomp_error=duplicate',
- 'jscomp_error=misplacedTypeAnnotation',
- ],
- 'disabled_closure_args': [], # remove the disabled closure args for more strict compilation
- },
- 'includes': ['../third_party/closure_compiler/compile_js.gypi'],
- },
- ],
+ 'target_name': 'compile_all_resources',
+ 'dependencies': [
+ # ... other projects ...
+++ '../my_project/compiled_resources2.gyp:*',
+ ],
+ }
+ ]
}
```
+
+This file is used by the
+[Closure compiler bot](http://build.chromium.org/p/chromium.fyi/builders/Closure%20Compilation%20Linux)
+to automatically compile your code on every commit.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698