Apache-ization, port to node.js

Whole lot of changes here:

* convert all files to use Apache license
* port server from Java to JavaScript using node.js
* various cleanups related to both of those issues

relevant issues:

* https://issues.apache.org/jira/browse/CB-10

  Apache source headers in callback-weinre

* https://issues.apache.org/jira/browse/CB-83

  implement the server in node

* https://issues.apache.org/jira/browse/CB-100

  fix issues regarding pre-req licenses for weinre distribution

* https://issues.apache.org/jira/browse/CB-176

  add vendor files to weinre instead of pulling in at build time
diff --git a/.wr b/.wr
new file mode 100644
index 0000000..7f87a8c
--- /dev/null
+++ b/.wr
@@ -0,0 +1,36 @@
+# ---
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# ---
+
+--stdoutcolor blue
+--stderrcolor red
+
+ant -f weinre.build/build.xml
+
+weinre.build/build.xml
+weinre.build/build.properties
+weinre.build/scripts
+weinre.doc
+weinre.server/interfaces
+weinre.server/lib
+weinre.server/package.json
+weinre.server/README.md
+weinre.server/weinre
+weinre.server/weinre-hot
+weinre.web
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8d776b4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,529 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+==============================================================
+This product also include the following software:
+==============================================================
+
+------------------------------------------
+WebKit Web Inspector
+Copyright multiple authors
+------------------------------------------
+
+Note that although WebKit in general contains both BSD and LGPL
+licensed code, the WebKit Web Inspector code is all BSD licensed
+with no LGPL code.  
+
+WebKit is available at
+
+    http://www.webkit.org/
+
+
+------------------------------------------
+Uglify is shipped with WebKit Web Inspector
+Copyright Mihai Bazon
+------------------------------------------
+
+                         Author: Mihai Bazon
+                       <mihai.bazon@gmail.com>
+                     http://mihai.bazon.net/blog
+
+Distributed under the BSD license:
+
+Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above
+      copyright notice, this list of conditions and the following
+      disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+------------------------------------------
+coffee-script 1.2.0 via npmjs.org
+
+https://github.com/jashkenas/coffee-script
+------------------------------------------
+
+Copyright (c) 2011 Jeremy Ashkenas
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+express 2.5.7 via npmjs.org
+
+https://github.com/visionmedia/express
+------------------------------------------
+
+(The MIT License)
+
+Copyright (c) 2009-2011 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+connect 1.8.5 via npmjs.org
+
+https://github.com/senchalabs/connect
+------------------------------------------
+
+(The MIT License)
+
+Copyright (c) 2010 Sencha Inc.
+Copyright (c) 2011 LearnBoost
+Copyright (c) 2011 TJ Holowaychuk
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+formidable 1.0.8 via npmjs.org
+
+https://github.com/felixge/node-formidable
+------------------------------------------
+
+Formidable is licensed under the MIT license.
+
+------------------------------------------
+mime 1.2.4 via npmjs.org
+
+https://github.com/bentomas/node-mime
+------------------------------------------
+
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------
+mkdirp 0.0.7 via npmjs.org
+
+https://github.com/substack/node-mkdirp
+------------------------------------------
+
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------
+qs 0.4.1 via npmjs.org
+
+https://github.com/visionmedia/node-querystring
+------------------------------------------
+
+(The MIT License)
+
+Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+nopt 1.0.10 via npmjs.org
+
+https://github.com/isaacs/nopt
+------------------------------------------
+
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+abbrev 1.0.3 via npmjs.org
+
+https://github.com/isaacs/abbrev-js
+------------------------------------------
+
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------
+underscore 1.3.1 via npmjs.org
+
+https://github.com/documentcloud/underscore
+------------------------------------------
+
+Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..b01a7cf
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Cordova weinre
+Copyright 2012 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 5d2773a..253b2e1 100644
--- a/README.md
+++ b/README.md
@@ -17,5 +17,144 @@
  * under the License.
 -->
 
+weinre is WEb INspector REmote. 
+Pronounced like the word "winery". 
+Or maybe like the word "weiner". 
+Who knows, really.
+
+weinre is a debugger for web pages, 
+like FireBug (for FireFox) and Web Inspector (for WebKit-based browsers), 
+except it's designed to work remotely, and in particular, 
+to allow you debug web pages on a mobile device such as a phone.
+
 For more information on weinre:
-[http://callback.github.com/callback-weinre/](http://callback.github.com/callback-weinre/)
\ No newline at end of file
+[http://http://incubator.apache.org/callback/](http://incubator.apache.org/callback/)
+
+
+weinre source
+-------------
+
+The weinre source is contained in 4 subdirectories:
+
+* `weinre.build` - contains the tools to build weinre, the 3rd party libraries
+that weinre uses, and holds the output of the build
+
+* `weinre.doc` - source for the HTML manual for weinre
+
+* `weinre.server` - code for the node.js-based weinre server
+
+* `weinre.web` - code for the client and target pieces of weinre
+
+
+building weinre
+---------------
+
+The weinre build is currently run on a Mac OS X 10.7 laptop.  It also runs on Apache
+continuous integration servers running Linux.  It is not typically run on Windows,
+so if you issues with that, please log an issue.  
+
+The weinre build pre-req's the following tools:
+
+* node.js - [http://nodejs.org/](http://nodejs.org/)
+* npm - should be shipped with node.js, on Linux may need to be installed as a separate
+package 
+* ant - [http://ant.apache.org/](http://ant.apache.org/)
+
+Before doing a weinre build, you will need to create the file
+`weinre.build/personal.properties`.  Use the `sample.personal.properties` as a template.
+The build should fail if this file is not available.
+
+To update the version label of weinre, edit the file `weinre.build/build.properties`.
+If the version has a `-pre` suffix, this triggers the build to artifacts with
+timestamped names.  For an 'official' build, do not use the `-pre` suffix.
+
+There are two ways to build weinre:
+
+* full build
+* development build
+
+The full build creates all the artifacts needed for an 'official' build.
+
+The development build just creates enough artifacts to test the code.
+
+### the first time you run any build: ###
+
+Some semi-transient artifacts are created the first time you run a build.
+These will be stored in the `weinre.build/cached` directory.
+
+### to perform the full build: ###
+
+* run: `cd weinre.build`
+* run: `ant`
+
+This will run the development build (see below), and then create zip archives of
+the build in the `weinre.build/out/archives` directory.
+
+### to perform the development build: ###
+
+* run: `cd weinre.build`
+* run: `ant build-dev`
+
+This will populate a number of resources in the `weinre.server` directory, so that
+you can run weinre directly from that directory for testing.  It does not build
+the archives.
+
+### performing a clean build: ###
+
+* run: `cd weinre.build`
+* run: `ant clean`
+* perform the build as usual
+
+### to run the output of the development build: ###
+
+* run: `cd weinre.server`
+* run: `./weinre [your flavorite options]`
+
+### other fun development-time hacks ###
+
+If you have the [wr tool](https://github.com/pmuellr/wr) installed, there are
+two `.wr` files available to run the two builds.  If you run `wr` in the top-level
+directory, a full build is performed when the source changes.  If you run `wr` in the
+`weinre.build` directory, a development-time build is performed.
+
+The build is growl-enabled, so you can see a quick message when the build completes.
+
+The command `weinre.server/weinre-hot` makes use of
+[node-supervisor](https://github.com/isaacs/node-supervisor) to re-launch the
+weinre server generated by the development build, whenever a weinre build
+completes.
+
+Putting this altogether, you can open two terminal windows, run `wr` in the `weinre.build`
+directory to have a development build run whenever you change the source, and then run `weinre.hot` in the `weinre.server` directory to have the weinre server restart whenever a build completes, getting a growl notification at that time.
+
+updating 3rd party libraries
+-----------------------------
+
+> **IMPORTANT** - All 3rd party libraries are stored in the SCM, so that the build does
+require 3rd party packages to be downloaded.  As such, these files need to be ok to 
+use and store in the SCM, given their licenses.  
+If you're adding or updating a 3rd party library, make
+sure the license is acceptable, and add/update the license in the top-level `LICENSE`
+file.
+
+All of the 3rd party dependencies used with weinre are stored in two directories:
+
+* `weinre.build/vendor` - contains libraries used in the client and/or target,
+as well as libraries used by the build itself
+
+* `weinre.server/node_modules` - contains npm packages used by the weinre.server
+
+
+To update the files in `weinre.build/vendor`:
+
+* edit the file `weinre.build/vendor.properties` as appropriate
+* run: `cd weinre.build`
+* run: `ant -f update.vendor.xml`
+
+To update the files in `weinre.server/node_modules`:
+
+* edit the file `weinre.build/package.json.template' as appropriate
+* run a build (see above), so that the file `weinre.server/package.json` file is created
+from the template you edited above
+* run: `cd weinre.server`
+* run: `npm install`
\ No newline at end of file
diff --git a/weinre.application/.classpath b/weinre.application/.classpath
deleted file mode 100644
index 4a626dc..0000000
--- a/weinre.application/.classpath
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry combineaccessrules="false" exported="true" kind="src" path="/weinre.server"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry exported="true" kind="lib" path="/weinre.build/vendor/swt/cocoa-macosx-x86_64/swt.jar" sourcepath="/weinre.build/vendor/swt/cocoa-macosx-x86_64/swt-src.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/weinre.application/.gitignore b/weinre.application/.gitignore
deleted file mode 100644
index ba077a4..0000000
--- a/weinre.application/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-bin
diff --git a/weinre.application/.project b/weinre.application/.project
deleted file mode 100644
index 4fcce84..0000000
--- a/weinre.application/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>weinre.application</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/weinre.application/resources/macosx/weinre.app/Contents/Info.plist b/weinre.application/resources/macosx/weinre.app/Contents/Info.plist
deleted file mode 100644
index f1b4861..0000000
--- a/weinre.application/resources/macosx/weinre.app/Contents/Info.plist
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
--->
-
-<plist version="1.0">
-<dict>
-    <key>CFBundleExecutable</key>
-        <string>launcher</string>
-    <key>CFBundleGetInfoString</key>
-        <string>weinre @VERSION@</string>
-    <key>CFBundleIconFile</key>
-        <string>weinre.icns</string>
-    <key>CFBundleIdentifier</key>
-        <string>weinre.application</string>
-    <key>CFBundleInfoDictionaryVersion</key>
-        <string>6.0</string>
-    <key>CFBundleName</key>
-        <string>weinre</string>
-    <key>CFBundlePackageType</key>
-        <string>APPL</string>
-    <key>CFBundleShortVersionString</key>
-        <string>weinre-@VERSION@</string>
-    <key>CFBundleSignature</key>
-        <string>????</string>
-    <key>CFBundleVersion</key>
-        <string>@VERSION@</string>
-    <key>NSPrincipalClass</key>
-        <string>NSApplication</string>
-</dict>
-</plist>
diff --git a/weinre.application/resources/macosx/weinre.app/Contents/MacOS/launcher b/weinre.application/resources/macosx/weinre.app/Contents/MacOS/launcher
deleted file mode 100644
index f76ffc5..0000000
--- a/weinre.application/resources/macosx/weinre.app/Contents/MacOS/launcher
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-# ---
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-# ---
-
-BASEDIR=`dirname $0`
-
-java \
-    -XstartOnFirstThread \
-    -classpath $BASEDIR/weinre-ui.jar:$BASEDIR/weinre.jar:$BASEDIR/swt.jar \
-    weinre.application.GUIMain
diff --git a/weinre.application/resources/macosx/weinre.app/Contents/Resources/weinre.icns b/weinre.application/resources/macosx/weinre.app/Contents/Resources/weinre.icns
deleted file mode 100644
index 0599724..0000000
--- a/weinre.application/resources/macosx/weinre.app/Contents/Resources/weinre.icns
+++ /dev/null
Binary files differ
diff --git a/weinre.application/src/weinre/application/GUIMain.java b/weinre.application/src/weinre/application/GUIMain.java
deleted file mode 100644
index 28208ff..0000000
--- a/weinre.application/src/weinre/application/GUIMain.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.application;
-
-import java.io.IOException;
-
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.MessageBox;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-import weinre.server.Main;
-import weinre.server.ServerSettings;
-
-//-------------------------------------------------------------------
-public class GUIMain extends Main {
-    private Display          display;
-    private Shell            shell;
-    private Browser          debugger;
-    private StyledText       console;
-    private Browser          homePage;
-    private Color            red;
-    private GUIPreferences   preferences;
-    private ShellSizeTracker shellSizeTracker;
-
-    //---------------------------------------------------------------
-    static public void main(String[] args) {
-        GUIMain main = new GUIMain(args);
-        main.run();
-    }
-
-    //---------------------------------------------------------------
-    private GUIMain(String[] args) {
-        super(args);
-
-        preferences = new GUIPreferences();
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public void run() {
-        uiBuild();
-
-        Runnable serverRunnable = new Runnable() {
-            public void run() {
-                httpServerStart();
-            }
-        };
-
-        new Thread(serverRunnable, "main server thread").start();
-
-        uiRun();
-
-        exit();
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public void serverStarted() {
-        debugger.getDisplay().asyncExec(new Runnable() {
-            public void run() {
-                debugger.getDisplay().timerExec(1000, new Runnable() {
-                    public void run() {
-                        debugger.setUrl(getBrowserURL() + "client/index.html");
-                        homePage.setUrl(getBrowserURL() + "index.html");
-                    }
-                });
-            }
-        });
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public void addServerConsoleMessage(final String line, final boolean stdout) {
-        if (null == console) return;
-
-        if (console.isDisposed()) return;
-
-        console.getDisplay().asyncExec(new Runnable() {
-           public void run() {
-               if (console.isDisposed()) return;
-
-               String theLine = line + Text.DELIMITER;
-
-               Color color = null;
-               if (!stdout) color = red;
-
-               StyleRange styleRange = new StyleRange();
-               styleRange.start      = console.getCharCount();
-               styleRange.length     = theLine.length();
-               styleRange.foreground = color;
-
-               console.append(theLine);
-               console.setStyleRange(styleRange);
-           }
-        });
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public int severeError(final String message) {
-        if (null == display) return super.severeError(message);
-        if (display.isDisposed()) return super.severeError(message);
-
-        display.syncExec(new Runnable() {
-           public void run() {
-               boolean noGUI = false;
-               if (null == display)      noGUI = true;
-               if (null == shell)        noGUI = true;
-               if (display.isDisposed()) noGUI = true;
-               if (shell.isDisposed())   noGUI = true;
-
-               if (noGUI) {
-                   GUIMain.super.severeError(message);
-                   return;
-               }
-
-               MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
-               messageBox.setMessage(message);
-               messageBox.setText("weinre exiting");
-               messageBox.open();
-               exit();
-           }
-        });
-
-        return 0;
-    }
-
-    //---------------------------------------------------------------
-    private void uiBuild() {
-        Display.setAppName("weinre");
-        Display.setAppVersion("???");
-
-        display = new Display();
-        shell   = new Shell(display);
-
-        red = new Color(display, 255, 0, 0);
-
-        shell.setText("weinre - Web Inspector Remote");
-
-        CTabFolder tabFolder       = new CTabFolder(shell, SWT.BORDER | SWT.BOTTOM);
-        CTabItem   tabItemDebugger = createTabItem(tabFolder, "Debugger");
-        CTabItem   tabItemConsole  = createTabItem(tabFolder, "Server Console");
-        CTabItem   tabItemHomePage = createTabItem(tabFolder, "Server Home Page");
-
-        debugger = new Browser(tabFolder, SWT.NONE);
-        tabItemDebugger.setControl(debugger);
-
-        console = new StyledText(tabFolder, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
-        console.setEditable(false);
-        console.setFont(getMonospaceFont(console));
-
-        homePage = new Browser(tabFolder, SWT.NONE);
-        tabItemHomePage.setControl(homePage);
-
-        tabItemConsole.setControl(console);
-
-        fillParent(debugger,  0, 0, 0, 0);
-        fillParent(console,   0, 0, 0, 0);
-        fillParent(homePage,  0, 0, 0, 0);
-        fillParent(tabFolder, 5, 5, 5, 5);
-
-        tabFolder.pack();
-        createMenuBar();
-
-        shellSizeTracker = new ShellSizeTracker("main", shell, preferences);
-        shellSizeTracker.start();
-
-        try {
-            String       boundsKey = ShellSizeTracker.getBoundsKey(shell, "main");
-            JSONObject   bounds    = preferences.getPreference(boundsKey);
-
-            if (null != bounds) {
-                Integer x, y, w, h;
-                try {
-                    x = bounds.getInt("x");
-                    y = bounds.getInt("y");
-                    w = bounds.getInt("width");
-                    h = bounds.getInt("height");
-                } catch (JSONException e) {
-                    throw new RuntimeException(e);
-                }
-
-                if ((null != w) && (null != h)) {
-                    shell.setBounds(x,y,w,h);
-                }
-            }
-
-            else {
-                shell.setBounds(100, 100, 700, 500);
-            }
-
-        }
-        catch (IOException e) {
-            Main.warn("exception reading preferences: " + e);
-        }
-
-    }
-
-    //---------------------------------------------------------------
-    private void createMenuBar() {
-//        Menu menu = new Menu(shell, SWT.BAR);
-//        shell.setMenuBar(menu);
-//        MenuItem fileMenuItem = new MenuItem(menu, SWT.CASCADE);
-//        fileMenuItem.setText("File");
-//        MenuItem editMenuItem = new MenuItem(menu, SWT.CASCADE);
-//        editMenuItem.setText("Edit");
-     }
-
-    //---------------------------------------------------------------
-    private void uiRun() {
-        shell.open();
-
-        while (!shell.isDisposed()) {
-            if (!display.readAndDispatch())
-                display.sleep();
-        }
-        display.dispose();
-    }
-
-    //---------------------------------------------------------------
-    private CTabItem createTabItem(CTabFolder tabFolder, String text) {
-        CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE);
-        tabItem.setText(text);
-
-        Font       font     = tabItem.getFont();
-        FontData[] fontData = font.getFontData();
-
-        for (FontData fontDatum: fontData) {
-            double newHeight = fontDatum.getHeight() * 1.25;
-            fontDatum.setHeight((int) newHeight);
-        }
-
-        font = new Font(display, fontData);
-        tabItem.setFont(font);
-
-        return tabItem;
-    }
-
-    //---------------------------------------------------------------
-    private void fillParent(Control control, int marginT, int marginR, int marginB, int marginL ) {
-        FormLayout formLayout = new FormLayout();
-
-        formLayout.marginTop    = marginT;
-        formLayout.marginBottom = marginB;
-        formLayout.marginLeft   = marginL;
-        formLayout.marginRight  = marginR;
-
-        FormData formData = new FormData();
-
-        formData.left     = new FormAttachment(0);
-        formData.right    = new FormAttachment(100);
-        formData.top      = new FormAttachment(0);
-        formData.bottom   = new FormAttachment(100);
-
-        control.getParent().setLayout(formLayout);
-        control.setLayoutData(formData);
-    }
-
-    //---------------------------------------------------------------
-    private String getBrowserURL() {
-        String result;
-
-        ServerSettings settings = weinre.server.Main.getSettings();
-
-        String host = settings.getNiceHostName();
-        int    port = settings.getHttpPort();
-
-        result = "http://" + host + ":" + port + "/";
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    private Font getMonospaceFont(Control control) {
-        FontData[] fontData = control.getDisplay().getFontList(null, true);
-
-        FontData fontFound = null;
-
-        // essentially the defaults that web inspector uses
-        if (null == fontFound) fontFound = findFontNamed(fontData, "Menlo");
-        if (null == fontFound) fontFound = findFontNamed(fontData, "Monaco");
-        if (null == fontFound) fontFound = findFontNamed(fontData, "Consolas");
-        if (null == fontFound) fontFound = findFontNamed(fontData, "Lucida Console");
-        if (null == fontFound) fontFound = findFontNamed(fontData, "dejavu sans mono");
-        if (null == fontFound) fontFound = findFontNamed(fontData, "Courier");
-
-        if (null == fontFound) return null;
-
-        fontFound.setHeight(14);
-
-        return new Font(control.getDisplay(), fontFound);
-    }
-
-    //---------------------------------------------------------------
-    private FontData findFontNamed(FontData[] fontData, String name) {
-        for (FontData fontDatum: fontData) {
-            if (fontDatum.getStyle() != SWT.NORMAL) continue;
-            if (name.equals(fontDatum.getName())) return fontDatum;
-        }
-
-        return null;
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings("unused")
-    private void dumpFontData(FontData[] fontData) {
-        for (FontData fontDatum: fontData) {
-            int    style       = fontDatum.getStyle();
-            String styleString = "";
-
-            if (0 != (style & SWT.NORMAL)) styleString += "NORMAL ";
-            if (0 != (style & SWT.BOLD))   styleString += "BOLD ";
-            if (0 != (style & SWT.ITALIC)) styleString += "ITALIC ";
-
-            styleString = styleString.trim();
-
-            System.out.println("font: " + fontDatum.getName() + " : " + fontDatum.getHeight() + " : " + styleString);
-        }
-    }
-
-}
diff --git a/weinre.application/src/weinre/application/GUIPreferences.java b/weinre.application/src/weinre/application/GUIPreferences.java
deleted file mode 100644
index 3751584..0000000
--- a/weinre.application/src/weinre/application/GUIPreferences.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.application;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-import weinre.server.Utility;
-
-
-//-------------------------------------------------------------------
-public class GUIPreferences {
-    static final private String PROPERTIES_FILE_NAME = "ui.properties";
-
-    private Properties properties;
-
-    //---------------------------------------------------------------
-    public GUIPreferences() {
-        super();
-
-        properties = Utility.readPropertiesFile(PROPERTIES_FILE_NAME);
-    }
-
-    //---------------------------------------------------------------
-    public JSONObject getPreference(String key) throws IOException {
-        String val = properties.getProperty(key);
-        if (null == val) return null;
-
-        try {
-            return new JSONObject(val);
-        } catch (JSONException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    //---------------------------------------------------------------
-    public void setPreference(String key, JSONObject json) {
-        String val = json.toString();
-
-        properties.setProperty(key, val);
-        Utility.writePropertiesFile(PROPERTIES_FILE_NAME, properties);
-    }
-
-}
diff --git a/weinre.application/src/weinre/application/ShellSizeTracker.java b/weinre.application/src/weinre/application/ShellSizeTracker.java
deleted file mode 100644
index e5d8972..0000000
--- a/weinre.application/src/weinre/application/ShellSizeTracker.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.application;
-
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Monitor;
-import org.eclipse.swt.widgets.Shell;
-
-//-------------------------------------------------------------------
-public class ShellSizeTracker {
-
-    private String         name;
-    private Shell          shell;
-    private GUIPreferences preferences;
-    private boolean        dirty;
-    private Point          lastSize;
-    private Point          lastLocation;
-    private long           lastChange;
-    private boolean        stop;
-
-    //---------------------------------------------------------------
-    static public String getBoundsKey(Shell shell, String name) {
-        return "bounds-" + name + "-" + ShellSizeTracker.getMonitorSetupKey(shell.getDisplay());
-    }
-
-    //---------------------------------------------------------------
-    static private String getMonitorSetupKey(final Display display) {
-        StringBuffer keyBuffer = new StringBuffer();
-
-        Monitor[] monitors = display.getMonitors();
-        for (Monitor monitor: monitors) {
-            Rectangle bounds     = monitor.getBounds();
-            Rectangle clientArea = monitor.getClientArea();
-
-            keyBuffer.append("__");
-            keyBuffer.append(bounds.x);      keyBuffer.append("_");
-            keyBuffer.append(bounds.y);      keyBuffer.append("_");
-            keyBuffer.append(bounds.width);  keyBuffer.append("_");
-            keyBuffer.append(bounds.height);
-
-            keyBuffer.append("__");
-            keyBuffer.append(clientArea.x);      keyBuffer.append("_");
-            keyBuffer.append(clientArea.y);      keyBuffer.append("_");
-            keyBuffer.append(clientArea.width);  keyBuffer.append("_");
-            keyBuffer.append(clientArea.height);
-        }
-
-        keyBuffer.insert(0, "monitor-setup");
-
-        return keyBuffer.toString();
-    }
-
-    //---------------------------------------------------------------
-    public ShellSizeTracker(String name, final Shell shell, GUIPreferences preferences) {
-        super();
-
-        this.name         = name;
-        this.shell        = shell;
-        this.preferences  = preferences;
-        this.dirty        = false;
-        this.lastSize     = new Point(0,0);
-        this.lastLocation = new Point(0,0);
-        this.stop         = false;
-
-        shell.addControlListener(new ControlListener() {
-            public void controlMoved(ControlEvent e)   {shellMoved();}
-            public void controlResized(ControlEvent e) {shellMoved();}
-        });
-
-    }
-
-    //---------------------------------------------------------------
-    public void start() {
-        startWaiterThread();
-    }
-
-    //---------------------------------------------------------------
-    public void stop() {
-
-    }
-
-    //---------------------------------------------------------------
-    private void shellMoved() {
-        dirty        = true;
-        lastChange   = System.currentTimeMillis();
-        lastLocation = shell.getLocation();
-        lastSize     = shell.getSize();
-    }
-
-    //---------------------------------------------------------------
-    private void checkForChanges() {
-        if (!dirty) return;
-        if (shell.isDisposed()) return;
-        if (System.currentTimeMillis() < lastChange + 3000) return;
-
-        JSONObject valueJSON = new JSONObject();
-
-        try {
-            valueJSON.put("x", lastLocation.x);
-            valueJSON.put("y", lastLocation.y);
-            valueJSON.put("width", lastSize.x);
-            valueJSON.put("height", lastSize.y);
-        } catch (JSONException e1) {
-            throw new RuntimeException(e1);
-        }
-
-        String key;
-        key = ShellSizeTracker.getBoundsKey(shell, name);
-
-        preferences.setPreference(key, valueJSON);
-
-        dirty = false;
-    }
-
-
-    //---------------------------------------------------------------
-    private Thread startWaiterThread() {
-        Runnable runnable = new Runnable() {
-            public void run() {
-                while (true) {
-                    try { Thread.sleep(1000); } catch(InterruptedException e) { return; }
-
-                    if (stop) return;
-                    if (shell.isDisposed()) return;
-
-                    shell.getDisplay().asyncExec(new Runnable() {
-                        public void run() { checkForChanges(); }
-                    });
-                }
-            }
-        };
-
-        Thread thread = new Thread(runnable, getClass().getSimpleName() + " for " + name);
-        thread.start();
-
-        return thread;
-    }
-
-}
diff --git a/weinre.application/weinre application using ~weinre-server.settings.launch b/weinre.application/weinre application using ~weinre-server.settings.launch
deleted file mode 100644
index 75a0fe3..0000000
--- a/weinre.application/weinre application using ~weinre-server.settings.launch
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/weinre.application/src/weinre/application/GUIMain.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="weinre.application.GUIMain"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="weinre.application"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread"/>
-</launchConfiguration>
diff --git a/weinre.build/.classpath b/weinre.build/.classpath
deleted file mode 100644
index 6e69b0c..0000000
--- a/weinre.build/.classpath
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="out"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/weinre.build/.gitignore b/weinre.build/.gitignore
index cdd5de8..dfb791d 100644
--- a/weinre.build/.gitignore
+++ b/weinre.build/.gitignore
@@ -2,7 +2,5 @@
 cached
 out
 tmp
-vendor
-node_modules
 
 personal.properties
\ No newline at end of file
diff --git a/weinre.build/.project b/weinre.build/.project
deleted file mode 100644
index 6d3107b..0000000
--- a/weinre.build/.project
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>weinre.build</name>
-	<comment></comment>
-	<projects>
-		<project>weinre.application</project>
-		<project>weinre.doc</project>
-		<project>weinre.playground</project>
-		<project>weinre.server</project>
-		<project>weinre.web</project>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/weinre.build/.wr b/weinre.build/.wr
new file mode 100644
index 0000000..c415783
--- /dev/null
+++ b/weinre.build/.wr
@@ -0,0 +1,35 @@
+# ---
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# ---
+
+--stdoutcolor blue
+--stderrcolor red
+
+./build-dev.sh
+
+../weinre.build/build.xml
+../weinre.build/build.properties
+../weinre.build/scripts
+../weinre.doc
+../weinre.server/interfaces
+../weinre.server/lib
+../weinre.server/package.json
+../weinre.server/README.md
+../weinre.server/weinre
+../weinre.server/weinre-hot
+../weinre.web
diff --git a/weinre.build/README.md b/weinre.build/README.md
deleted file mode 100644
index e47c046..0000000
--- a/weinre.build/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
--->
-
-building weinre
-===============================================================================
-
-The weinre source base consists of file folders:
-
-- `weinre.application`
-- `weinre.build`
-- `weinre.doc`
-- `weinre.server`
-- `weinre.web`
-
-weinre was originally built using Eclipse, and still maintains Eclipse meta-data so that it can be developed in Eclipse.  Each of the folders above maps into a separate project.  Note however that the Eclipse-y-ness of the weinre source base is no longer maintained.  Please open a bug if there are problems.
-
-Before running a build, you should copy the `weinre.build/sample.personal.properties` file to the file `weinre.build/personal.properties`, and then customize that file.
-
-weinre requires additional code to produce the final jar.  These dependencies will be downloaded the first time you run a build, and then won't be downloaded for subsequent builds.  You can explicitly get the dependencies by running the `weinre.build/get-vendor.xml` file in Ant, as follows:
-
-    ant -f get-vendor.xml
-
-Various transient directories in this project (weinre.build) will be created after the build.  They are set to not be stored in the SCM.  They include:
-
-- `out`
-- `cached`
-- `tmp`
-- `vendor`
-
-You can delete them whenever you wish, or use the `"clean"` target of the  `weinre.build/build.xml` file to delete them.  Deleting them will cause the build to take longer, to rebuild what you deleted.
-
-The `weinre.build/out` directory in particular contains the final build artifacts:
-
--  `weinre.build/out/archives/weinre-doc-{version}.zip`
-
-   contains the HTML doc for weinre
-
--  `weinre.build/out/archives/weinre-jar-{version}.zip`
-
-   contains the platform-portable weinre.jar file
-
--  `weinre.build/out/archives/weinre-mac-{version}.zip`
-
-   contains the Mac OS X weinre.app application
-
--  `weinre.build/out/archives/weinre-src-{version}.zip`
-
-   contains the source of the projects (copy of what's in the SCM)
-
-To build while you are developing the weinre code, you can use the quicker-to-build `"build-dev"` target of `weinre.build/build.xml` . This will not build the jars or archives, just rebuilds the bits necessary to run the server transient output directories.
diff --git a/weinre.build/build-continuous.sh b/weinre.build/build-continuous.sh
deleted file mode 100755
index e6f1181..0000000
--- a/weinre.build/build-continuous.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-# ---
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-# ---
-
-#-------------------------------------------------------------
-# create a link to your workspace first!
-#-------------------------------------------------------------
-EWS=~/weinre-workspace
-
-cd $EWS/weinre.build
-
-#-------------------------------------------------------------
-# run-when-changed: https://gist.github.com/240922
-#-------------------------------------------------------------
-
-run-when-changed "ant build" \
-  ../weinre.application \
-  ../weinre.build/*.xml \
-  ../weinre.build/*.properties \
-  ../weinre.build/scripts \
-  ../weinre.doc \
-  ../weinre.server \
-  ../weinre.web
-
diff --git a/weinre.build/build-dev.sh b/weinre.build/build-dev.sh
new file mode 100755
index 0000000..2d8991f
--- /dev/null
+++ b/weinre.build/build-dev.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# ---
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# ---
+
+# this script builds enough of weinre to test at development time
+
+cd `dirname $0`
+ant build-dev
\ No newline at end of file
diff --git a/weinre.build/build.properties b/weinre.build/build.properties
index 8cb1b96..a1fe6d5 100644
--- a/weinre.build/build.properties
+++ b/weinre.build/build.properties
@@ -20,7 +20,8 @@
 #-----------------------------------------------------------
 # weinre version
 #-----------------------------------------------------------
-WEINRE_VERSION: 1.6.1
+
+WEINRE_VERSION: 1.7.0-pre
 
 #-----------------------------------------------------------
 # some common locations used in the ant scripts
@@ -28,7 +29,7 @@
 
 TMP:    tmp
 OUT:    out
-WEB:    out/web
+WEB:    ../weinre.server/web
 CACHED: cached
 VENDOR: vendor
 
diff --git a/weinre.build/build.xml b/weinre.build/build.xml
index eab7546..21efe08 100644
--- a/weinre.build/build.xml
+++ b/weinre.build/build.xml
@@ -39,20 +39,32 @@
     </tstamp>
 
     <tstamp>
-        <format property="BUILD_NUMBER_DATE" pattern="yyyy-MM-dd--HH-mm-ss" timezone="GMT"/>
+        <format property="BUILD_DATE" pattern="yyyy-MM-dd--HH-mm-ss" timezone="GMT"/>
     </tstamp>
 
-    <property name="BUILD_NUMBER" value="${WEINRE_VERSION}build-${BUILD_NUMBER_DATE}"/>
+    <condition property="BUILD_VERSION" value="${WEINRE_VERSION}-${BUILD_DATE}">
+        <matches pattern=".*pre$" string="${WEINRE_VERSION}"/>
+    </condition>
+    
+    <condition property="BUILD_VERSION" value="${WEINRE_VERSION}">
+        <not>
+            <matches pattern=".*pre$" string="${WEINRE_VERSION}"/>
+        </not>
+    </condition>
+    
+    <!-- ============================================================
+         do a clean build
+         ============================================================ -->
 
+    <target name="build-clean" depends="clean,build">
+    </target>
 
     <!-- ============================================================
          main entry point
          ============================================================ -->
 
     <target name="build" depends="build-dev">
-        <antcall target="build-jar"/>
-        <antcall target="build-ui-jar"/>
-        <antcall target="build-application-mac"/>
+        <antcall target="build-doc"/>
         <antcall target="build-archives"/>
 
         <echo>full ant build completed successfully</echo>
@@ -64,12 +76,9 @@
 
     <target name="clean">
         <delete dir="${OUT}"/>
-        <mkdir  dir="${OUT}"/> <!-- this is an Eclipse source folder! -->
-
         <delete dir="${TMP}"/>
+        <delete dir="${WEB}"/>
         <delete dir="${CACHED}"/>
-        <delete dir="${VENDOR}"/>
-        <delete dir="node_modules"/>
     </target>
 
     <!-- ============================================================
@@ -77,20 +86,32 @@
          ============================================================ -->
 
     <target name="build-dev">
-        <delete dir="${OUT}"/>
-        <mkdir  dir="${OUT}"/>
+        <fail>
+            <condition>
+                <not>
+                    <resourceexists>
+                        <file file="personal.properties"/>
+                    </resourceexists>
+                </not>
+            </condition>
+            The file 'personal.properties' was not found; create one based on 'sample.personal.properties'.
+        </fail>
 
+        <echo>building version ${BUILD_VERSION}</echo>
+
+        <mkdir  dir="${OUT}"/>
+        <delete includeemptydirs="true">
+            <fileset dir="${OUT}" includes="**/*" excludes="build-done.txt"/>
+        </delete>        
+        
         <property
             name  = "build-info-text"
-            value = "weinre build ${BUILD_NUMBER} by ${BUILDER}"
+            value = "weinre build ${BUILD_VERSION} by ${BUILDER}"
         />
 
         <echo file="${OUT}/build-info.txt" message="${build-info-text}"/>
 
-        <antcall target="build-vendor"/>
-        <antcall target="compile-java"/>
         <antcall target="build-web"/>
-        <antcall target="build-doc"/>
         <antcall target="build-json-idl"/>
         <antcall target="build-client"/>
         <antcall target="build-target"/>
@@ -103,54 +124,16 @@
 
         <antcall target="finished"/>
         <antcall target="finished-growl"/>
+        
+        <echo file="${OUT}/build-done.txt" message="${build-info-text} is finished!"/>
+        
     </target>
 
     <!-- ============================================================
-         compile java code
+         check for personal properties
          ============================================================ -->
 
-    <target name="compile-java" unless="USE_ECLIPSE">
-        <delete dir="../${PROJECT_SERVER}/bin"/>
-        <mkdir  dir="../${PROJECT_SERVER}/bin"/>
-
-        <javac
-            srcdir            = "../${PROJECT_SERVER}/src"
-            destdir           = "../${PROJECT_SERVER}/bin"
-            debug             = "true"
-            verbose           = "false"
-            includeAntRuntime = "false"
-        >
-            <classpath path="../${PROJECT_BUILD}/vendor/cli/commons-cli.jar"/>
-            <classpath path="../${PROJECT_BUILD}/vendor/jetty/jetty.jar"/>
-            <classpath path="../${PROJECT_BUILD}/vendor/json4j/json4j.jar"/>
-            <classpath path="../${PROJECT_BUILD}/vendor/jetty/servlet-api.jar"/>
-            <compilerarg value="-Xlint"/>
-        </javac>
-
-        <delete dir="../${PROJECT_APPLICATION}/bin"/>
-        <mkdir  dir="../${PROJECT_APPLICATION}/bin"/>
-
-        <javac
-            srcdir            = "../${PROJECT_APPLICATION}/src"
-            destdir           = "../${PROJECT_APPLICATION}/bin"
-            debug             = "true"
-            verbose           = "false"
-            includeAntRuntime = "false"
-        >
-            <classpath path="../${PROJECT_SERVER}/bin"/>
-            <classpath path="../${PROJECT_BUILD}/vendor/json4j/json4j.jar"/>
-            <classpath path="../${PROJECT_BUILD}/vendor/swt/cocoa-macosx-x86_64/swt.jar"/>
-            <compilerarg value="-Xlint"/>
-        </javac>
-
-    </target>
-
-    <!-- ============================================================
-         build vendor libs
-         ============================================================ -->
-
-    <target name="build-vendor" unless="VENDOR_FOUND">
-        <ant antfile="get-vendor.xml"/>
+    <target name="check-personal-properties" unless="personal.properties.exists">
     </target>
 
     <!-- ============================================================
@@ -172,24 +155,24 @@
         <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/client"/>
         <exec executable="sh" failonerror="true" failifexecutionfails="true">
             <arg value="-c"/>
-            <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/client ../${PROJECT_WEB}/modules/weinre/client/*.coffee"/>
+            <arg value="${VENDOR}/node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/client ../${PROJECT_WEB}/modules/weinre/client/*.coffee"/>
         </exec>
 
         <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/common"/>
         <exec executable="sh" failonerror="true" failifexecutionfails="true">
             <arg value="-c"/>
-            <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/common ../${PROJECT_WEB}/modules/weinre/common/*.coffee"/>
+            <arg value="${VENDOR}/node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/common ../${PROJECT_WEB}/modules/weinre/common/*.coffee"/>
         </exec>
 
         <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/target"/>
         <exec executable="sh" failonerror="true" failifexecutionfails="true">
             <arg value="-c"/>
-            <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/target ../${PROJECT_WEB}/modules/weinre/target/*.coffee"/>
+            <arg value="${VENDOR}/node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/target ../${PROJECT_WEB}/modules/weinre/target/*.coffee"/>
         </exec>
 
         <echo message="transportd-izing modules"/>
         <exec executable="python" failonerror="true" failifexecutionfails="true">
-            <arg  file="vendor/modjewel/module2transportd.py"/>
+            <arg  file="scripts/module2amd.py"/>
             <arg value="--quiet"/>
             <arg value="--out"/>
             <arg  file="${WEB}"/>
@@ -197,12 +180,14 @@
         </exec>
 
         <copy todir="${WEB}">
-            <fileset file="${VENDOR}/modjewel/modjewel-require.js"/>
+            <fileset file="../${PROJECT_WEB}/modjewel.js"/>
         </copy>
 
+<!--
         <copy todir="${WEB}">
             <fileset file="${VENDOR}/json2/json2.js"/>
         </copy>
+-->
 
         <copy todir="${WEB}">
             <fileset dir="../${PROJECT_WEB}">
@@ -235,30 +220,17 @@
             </fileset>
 
             <filterset>
-                <filter token="WEINRE_VERSION"             value="${WEINRE_VERSION}"/>
-                <filter token="BUILD_NUMBER"               value="${BUILD_NUMBER}"/>
-                <filter token="BUILD_NUMBER_DATE"          value="${BUILD_NUMBER_DATE}"/>
-                <filter token="CLI_VERSION"                value="${CLI_VERSION}"/>
-                <filter token="JSON4J_VERSION"             value="${JSON4J_VERSION}"/>
-                <filter token="JSON2_VERSION"              value="${JSON2_VERSION}"/>
-                <filter token="WEBKIT_VERSION"             value="${WEBKIT_VERSION}"/>
-                <filter token="SWT_VERSION"                value="${SWT_VERSION}"/>
-                <filter token="JETTY_VERSION"              value="${JETTY_VERSION}"/>
-                <filter token="MODJEWEL_VERSION"           value="${MODJEWEL_VERSION}"/>
-                <filter token="JAVAX_SERVLET_VERSION"      value="${JAVAX_SERVLET_VERSION}"/>
-                <filter token="JAVAX_SERVLET_VERSION_IMPL" value="${JAVAX_SERVLET_VERSION_IMPL}"/>
+                <filter token="WEINRE_VERSION" value="${BUILD_VERSION}"/>
+                <filter token="BUILD_DATE"     value="${BUILD_DATE}"/>
             </filterset>
         </copy>
 
-<!--
-        <echo message="building add-css-properties.js"/>
-        <exec executable="python" failonerror="true" failifexecutionfails="true">
-            <arg  file="scripts/build-css-properties.py"/>
-            <arg value="vendor/webkit/WebCore/CSSPropertyNames.in"/>
-            <arg value="${WEB}/add-css-properties.js"/>
-        </exec>
--->
-
+        <echo message="building package.json"/>
+        <copy file="package.json.template"  tofile="../${PROJECT_SERVER}/package.json" overwrite="true">
+            <filterset>
+                <filter token="WEINRE_VERSION" value="${BUILD_VERSION}"/>
+            </filterset>
+        </copy>
     </target>
 
     <!-- ============================================================
@@ -387,99 +359,6 @@
     </target>
 
     <!-- ============================================================
-         build the main jar
-         ============================================================ -->
-
-    <target name="build-jar">
-
-        <jar destfile="${OUT}/weinre.jar">
-            <manifest>
-                <attribute name="Built-By" value="${ant.file.basename} - ${ant.project.name}"/>
-                <attribute name="Main-Class" value="weinre.server.Main"/>
-            </manifest>
-
-            <fileset file="${OUT}/build-info.txt"/>
-
-            <zipfileset src="${VENDOR}/jetty/jetty.jar">
-                <exclude name="about*.html"/>
-                <exclude name="META-INF/**/*"/>
-            </zipfileset>
-
-            <zipfileset src="${VENDOR}/jetty/servlet-api.jar">
-                <exclude name="META-INF/**/*"/>
-            </zipfileset>
-
-            <zipfileset src="${VENDOR}/cli/commons-cli.jar">
-                <exclude name="META-INF/**/*"/>
-            </zipfileset>
-
-            <zipfileset src="${VENDOR}/json4j/json4j.jar">
-                <exclude name="META-INF/**/*"/>
-            </zipfileset>
-
-            <fileset dir="../${PROJECT_SERVER}/bin"/>
-
-            <zipfileset dir="${WEB}" prefix="web"/>
-        </jar>
-
-    </target>
-
-    <!-- ============================================================
-         build the ui jar
-         ============================================================ -->
-
-    <target name="build-ui-jar">
-
-        <fileset dir="../${PROJECT_APPLICATION}/bin"/>
-
-        <jar destfile="${OUT}/weinre-ui.jar">
-            <manifest>
-                <attribute name="Built-By" value="${ant.file.basename} - ${ant.project.name}"/>
-                <attribute name="Main-Class" value="weinre.application.GUIMain"/>
-            </manifest>
-
-            <fileset file="${OUT}/build-info.txt"/>
-
-            <fileset dir="../${PROJECT_APPLICATION}/bin"/>
-
-            <zipfileset src="${VENDOR}/swt/cocoa-macosx-x86_64/swt.jar">
-                <exclude name="META-INF/**/*"/>
-            </zipfileset>
-        </jar>
-
-    </target>
-
-    <!-- ============================================================
-         build the mac application
-         ============================================================ -->
-
-    <target name="build-application-mac">
-        <delete dir="${OUT}/applications/mac"/>
-        <mkdir  dir="${OUT}/applications/mac/weinre.app"/>
-
-        <copy todir="${OUT}/applications/mac/weinre.app">
-            <fileset dir="../${PROJECT_APPLICATION}/resources/macosx/weinre.app">
-                <exclude name="**/Info.plist"/>
-            </fileset>
-        </copy>
-
-        <copy todir="${OUT}/applications/mac/weinre.app">
-            <fileset dir="../${PROJECT_APPLICATION}/resources/macosx/weinre.app">
-                <include name="**/Info.plist"/>
-            </fileset>
-            <filterset>
-                <filter token="VERSION" value="${WEINRE_VERSION}"/>
-            </filterset>
-        </copy>
-
-        <chmod file="${OUT}/applications/mac/weinre.app/Contents/MacOS/launcher" perm="+x"/>
-        <copy todir="${OUT}/applications/mac/weinre.app/Contents/MacOS" file="${OUT}/weinre.jar" />
-        <copy todir="${OUT}/applications/mac/weinre.app/Contents/MacOS" file="${OUT}/weinre-ui.jar"/>
-        <copy todir="${OUT}/applications/mac/weinre.app/Contents/Resources" file="${OUT}/build-info.txt"/>
-
-    </target>
-
-    <!-- ============================================================
          build the archives
          ============================================================ -->
     <target name="build-archives">
@@ -490,67 +369,64 @@
 
         <delete dir="${OUT}/files"/>
 
-        <delete dir="${OUT}/files/weinre-jar"/>
-        <mkdir  dir="${OUT}/files/weinre-jar"/>
-        <copy todir="${OUT}/files/weinre-jar" file="${OUT}/build-info.txt"/>
-        <copy todir="${OUT}/files/weinre-jar" file="${OUT}/weinre.jar"/>
-
-        <!-- ant's zip task doesn't preserve permission bits -->
-        <exec executable="zip" dir="${OUT}/files">
-            <arg value="-q"/>
-            <arg value="-r"/>
-            <arg value="../archives/weinre-jar-${BUILD_NUMBER}.zip"/>
-            <arg value="weinre-jar"/>
-        </exec>
-
-        <!-- =================================== -->
-        <delete dir="${OUT}/files/weinre-mac"/>
-        <mkdir  dir="${OUT}/files/weinre-mac"/>
-        <copy todir="${OUT}/files/weinre-mac" file="${OUT}/build-info.txt" />
-        <copy todir="${OUT}/files/weinre-mac">
-            <fileset dir="${OUT}/applications/mac"/>
+        <delete dir="${OUT}/files/weinre-node"/>
+        <mkdir  dir="${OUT}/files/weinre-node"/>
+        <copy todir="${OUT}/files/weinre-node" file="${OUT}/build-info.txt"/>
+        <copy todir="${OUT}/files/weinre-node" file="../LICENSE"/>
+        <copy todir="${OUT}/files/weinre-node" file="../NOTICE"/>
+        <copy todir="${OUT}/files/weinre-node">
+            <fileset dir="../${PROJECT_SERVER}"/>
         </copy>
-        <chmod file="${OUT}/files/weinre-mac/weinre.app/Contents/MacOS/launcher" perm="+x"/>
 
         <!-- ant's zip task doesn't preserve permission bits -->
         <exec executable="zip" dir="${OUT}/files">
             <arg value="-q"/>
             <arg value="-r"/>
-            <arg value="../archives/weinre-mac-${BUILD_NUMBER}.zip"/>
-            <arg value="weinre-mac"/>
+            <arg value="../archives/weinre-node-${BUILD_VERSION}.zip"/>
+            <arg value="weinre-node"/>
         </exec>
 
         <!-- =================================== -->
         <delete dir="${OUT}/files/weinre-doc"/>
         <mkdir  dir="${OUT}/files/weinre-doc"/>
         <copy todir="${OUT}/files/weinre-doc" file="${OUT}/build-info.txt" />
+        <copy todir="${OUT}/files/weinre-doc" file="../LICENSE"/>
+        <copy todir="${OUT}/files/weinre-doc" file="../NOTICE"/>
         <copy todir="${OUT}/files/weinre-doc">
-            <fileset dir="${OUT}/web/doc"/>
+            <fileset dir="${WEB}/doc"/>
         </copy>
 
         <!-- ant's zip task doesn't preserve permission bits -->
         <exec executable="zip" dir="${OUT}/files">
             <arg value="-q"/>
             <arg value="-r"/>
-            <arg value="../archives/weinre-doc-${BUILD_NUMBER}.zip"/>
+            <arg value="../archives/weinre-doc-${BUILD_VERSION}.zip"/>
             <arg value="weinre-doc"/>
         </exec>
 
         <!-- =================================== -->
         <delete dir="${OUT}/files/weinre-src"/>
         <mkdir  dir="${OUT}/files/weinre-src"/>
+        <exec executable="git" dir="..">
+            <arg value="archive"/>
+            <arg value="--format=zip"/>
+            <arg value="--prefix=weinre-src/"/>
+            <arg value="--output=${PROJECT_BUILD}/${TMP}/weinre-src.zip"/>
+            <arg value="HEAD"/>
+        </exec>
+
+        <exec executable="unzip" dir="${OUT}/files">
+            <arg value="-q"/>
+            <arg value="../../${TMP}/weinre-src.zip"/>
+        </exec>
+        
         <copy todir="${OUT}/files/weinre-src" file="${OUT}/build-info.txt" />
-        <copy todir="${OUT}/files/weinre-src/weinre.application"> <fileset dir="../weinre.application" excludes="**/bin/"/></copy>
-        <copy todir="${OUT}/files/weinre-src/weinre.build">       <fileset dir="../weinre.build"       excludes="**/bin/, **/out/, **/cached/, **/vendor/, **/tmp/, **/node_modules/"/></copy>
-        <copy todir="${OUT}/files/weinre-src/weinre.doc">         <fileset dir="../weinre.doc"         excludes="**/bin/"/></copy>
-        <copy todir="${OUT}/files/weinre-src/weinre.server">      <fileset dir="../weinre.server"      excludes="**/bin/"/></copy>
-        <copy todir="${OUT}/files/weinre-src/weinre.web">         <fileset dir="../weinre.web"         excludes="**/bin/"/></copy>
 
         <!-- ant's zip task doesn't preserve permission bits -->
         <exec executable="zip" dir="${OUT}/files">
             <arg value="-q"/>
             <arg value="-r"/>
-            <arg value="../archives/weinre-src-${BUILD_NUMBER}.zip"/>
+            <arg value="../archives/weinre-src-${BUILD_VERSION}.zip"/>
             <arg value="weinre-src"/>
         </exec>
 
diff --git a/weinre.build/debug.sh b/weinre.build/debug.sh
deleted file mode 100755
index ba681ee..0000000
--- a/weinre.build/debug.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-# ---
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-# ---
-
-CWD=`dirname $0`
-WEINRE=`dirname $CWD`
-CP=$WEINRE/weinre.server/bin:$WEINRE/weinre.build/out:$WEINRE/weinre.build/vendor/cli/commons-cli.jar:$WEINRE/weinre.build/vendor/jetty/jetty.jar:$WEINRE/weinre.build/vendor/json4j/json4j.jar:$WEINRE/weinre.build/vendor/jetty/servlet-api.jar
-PORT=8096
-DEBUG=jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:$PORT
-
-java \
-	-agentlib:$DEBUG \
-	-Dfile.encoding=UTF-8 \
-	-classpath $CP \
-	weinre.server.Main \
-	--deathTimeout 120
diff --git a/weinre.build/get-vendor.xml b/weinre.build/get-vendor.xml
deleted file mode 100644
index e420835..0000000
--- a/weinre.build/get-vendor.xml
+++ /dev/null
@@ -1,207 +0,0 @@
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
--->
-
-<project name="get-vendor" default="get-vendor" basedir=".">
-
-    <property file="personal.properties"/>
-    <property file="build.properties"/>
-    <property file="vendor.properties"/>
-
-    <!-- ============================================================ -->
-
-    <target name="get-vendor">
-        <echo>Go get some coffee, this is going to take a while</echo>
-
-        <delete dir="${TMP}"/>
-
-        <delete dir="${VENDOR}"/>
-        <mkdir  dir="${VENDOR}"/>
-
-        <antcall target="get-json2"/>
-        <antcall target="get-cli"/>
-        <antcall target="get-json4j"/>
-        <antcall target="get-jetty"/>
-        <antcall target="get-coffeescript"/>
-        <antcall target="get-modjewel"/>
-        <antcall target="get-web-inspector"/>
-        <antcall target="get-swt-mac"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-cli">
-        <delete dir="${VENDOR}/cli"/>
-        <mkdir  dir="${VENDOR}/cli"/>
-
-        <delete dir="${TMP}"/>
-        <mkdir  dir="${TMP}"/>
-
-        <get src="${CLI_URL}" dest="${TMP}/commons-cli.zip" verbose="false"/>
-        <unzip src="${TMP}/commons-cli.zip" dest="${TMP}">
-            <patternset>
-                <include name="${CLI_BASENAME}-sources.jar"/>
-                <include name="${CLI_BASENAME}.jar"/>
-            </patternset>
-        </unzip>
-
-
-        <copy file="${TMP}/${CLI_BASENAME}.jar"         tofile="${VENDOR}/cli/commons-cli.jar"/>
-        <copy file="${TMP}/${CLI_BASENAME}-sources.jar" tofile="${VENDOR}/cli/commons-cli-src.jar"/>
-
-        <delete dir="${TMP}"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-json4j">
-        <delete dir="${VENDOR}/json4j"/>
-        <mkdir  dir="${VENDOR}/json4j"/>
-
-        <delete dir="${TMP}"/>
-        <mkdir  dir="${TMP}"/>
-
-        <get src="${JSON4J_BIN_URL}" dest="${TMP}/json4j.zip" verbose="false"/>
-        <unzip src="${TMP}/json4j.zip" dest="${TMP}">
-            <patternset>
-                <include name="**/wink-json4j-${JSON4J_VERSION}.jar"/>
-            </patternset>
-        </unzip>
-
-        <copy file="${TMP}/apache-wink-${JSON4J_VERSION}/ext/wink-json4j-provider/lib/wink-json4j-${JSON4J_VERSION}.jar" tofile="${VENDOR}/json4j/json4j.jar"/>
-
-        <delete dir="${TMP}"/>
-        <mkdir  dir="${TMP}"/>
-        <get src="${JSON4J_SRC_URL}" dest="${TMP}/json4j-src.zip" verbose="false"/>
-        <unzip src="${TMP}/json4j-src.zip" dest="${TMP}/src">
-            <patternset>
-                <include name="**/wink-json4j/src/main/java/org/apache/wink/json4j/**/*"/>
-            </patternset>
-        </unzip>
-
-        <zip destfile="${VENDOR}/json4j/json4j-src.jar" basedir="${TMP}/src"/>
-
-        <delete dir="${TMP}"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-jetty">
-        <delete dir="${VENDOR}/jetty"/>
-        <mkdir  dir="${VENDOR}/jetty"/>
-
-        <get src="${JETTY_SRC_URL}"     dest="${VENDOR}/jetty/jetty-src.jar"   verbose="false"/>
-        <get src="${JETTY_BIN_URL}"     dest="${VENDOR}/jetty/jetty.jar"       verbose="false"/>
-        <get src="${JAVAX_SERVLET_URL}" dest="${VENDOR}/jetty/servlet-api.jar" verbose="false"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-coffeescript">
-        <echo message="coffee-script@${COFFEESCRIPT_VERSION}"/>
-        <exec executable="npm">
-            <arg value="install"/>
-            <arg value="coffee-script@${COFFEESCRIPT_VERSION}"/>
-        </exec>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-modjewel">
-        <delete dir="${VENDOR}/modjewel"/>
-        <mkdir  dir="${VENDOR}/modjewel"/>
-
-        <get src="${MODJEWEL_URL_PREFIX}/modjewel-require.js"  dest="${VENDOR}/modjewel/modjewel-require.js"  verbose="false"/>
-        <get src="${MODJEWEL_URL_PREFIX}/module2transportd.py" dest="${VENDOR}/modjewel/module2transportd.py" verbose="false"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-web-inspector">
-        <delete dir="${VENDOR}/webkit"/>
-        <mkdir  dir="${VENDOR}/webkit/WebCore"/>
-
-        <exec executable="svn" dir="${VENDOR}/webkit/WebCore">
-            <arg value="--non-interactive"/>
-            <arg value="--trust-server-cert"/>
-            <arg value="export"/>
-            <arg value="-r"/>
-            <arg value="${WEBKIT_VERSION}"/>
-            <arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/inspector"/>
-        </exec>
-
-        <exec executable="svn" dir="${VENDOR}/webkit/WebCore">
-            <arg value="--non-interactive"/>
-            <arg value="--trust-server-cert"/>
-            <arg value="export"/>
-            <arg value="-r"/>
-            <arg value="${WEBKIT_VERSION}"/>
-            <arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/English.lproj"/>
-        </exec>
-
-        <exec executable="svn" dir="${VENDOR}/webkit/WebCore">
-            <arg value="--non-interactive"/>
-            <arg value="--trust-server-cert"/>
-            <arg value="export"/>
-            <arg value="-r"/>
-            <arg value="${WEBKIT_VERSION}"/>
-            <arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/css/CSSPropertyNames.in"/>
-        </exec>
-
-        <exec executable="grep" outputproperty="gpl-grep-results" dir="${VENDOR}/webkit/WebCore">
-            <arg value="-r"/>
-            <arg value="GPL"/>
-            <arg value="."/>
-        </exec>
-
-        <condition property="found-no-gpl-files">
-            <equals arg1="" arg2="${gpl-grep-results}"/>
-        </condition>
-
-        <fail unless="found-no-gpl-files" message="The string GPL was found in the WebKit files"/>
-
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-swt-mac">
-        <delete dir="${VENDOR}/swt"/>
-        <mkdir  dir="${VENDOR}/swt"/>
-
-        <delete dir="${TMP}"/>
-        <mkdir dir="${TMP}"/>
-
-        <get src="${SWT_URL_PREFIX}/swt-${SWT_VERSION_MAJOR}-cocoa-macosx-x86_64.zip" dest="${TMP}/swt.zip" verbose="false"/>
-        <unzip src="${TMP}/swt.zip" dest="${TMP}"/>
-
-        <copy file="${TMP}/src.zip"       tofile="${VENDOR}/swt/cocoa-macosx-x86_64/swt-src.jar"/>
-        <copy file="${TMP}/swt-debug.jar" tofile="${VENDOR}/swt/cocoa-macosx-x86_64/swt.jar"/>
-
-        <delete dir="${TMP}"/>
-    </target>
-
-    <!-- ============================================================ -->
-
-    <target name="get-json2">
-        <delete dir="${VENDOR}/json2"/>
-        <mkdir  dir="${VENDOR}/json2"/>
-
-        <get src="${JSON2_URL_PREFIX}/json2.js"  dest="${VENDOR}/json2/json2.js"  verbose="false"/>
-    </target>
-
-</project>
diff --git a/weinre.build/new-release-notes.md b/weinre.build/new-release-notes.md
index 46f9a71..cbbbce6 100644
--- a/weinre.build/new-release-notes.md
+++ b/weinre.build/new-release-notes.md
@@ -24,62 +24,48 @@
 
 - update the `WEINRE_VERSION` variable in `weinre.build/build.properties` as appropriate
 
-- add changelog to `weinre.doc/ChangeLog.body.html`, built with
-
-    weinre.build/scripts/changelog.sh [previous-version]
+- add changelog to `weinre.doc/ChangeLog.body.html`
 
 - fix other doc as necessary
 
-- perform full build with one of:
+- perform full build with:
 
    - cd into `weinre.build` and run ant
 
-   - in Eclipse, select `weinre build.xml` from the External Tools menu
-
 - run the smoke test (see below) to ensure delicious smoky flavor
 
-- upload the `weinre-jar-x.y.z.zip` and `weinre-mac-x.y.z.zip` files
+- upload the `weinre-*-x.y.z.zip`
 
 - make sure you can download those zip files!
 
 - commit release changes:
    - `git add .`
-   - `git commit -m update for release x.y.z`
+   - `git commit -m "update for release x.y.z"`
 
 - merge branch onto master:
 
    - `git checkout master`
-   - `git merge --no-ff release-x.y.z`
+   - `git merge release-x.y.z`
    - `git push`
    - `git tag -a x.y.z`
    - `git push --tags`
 
-- merge branch onto develop:
+- update apache cms pages:
 
-   - `git checkout develop`
-   - `git merge --no-ff release-x.y.z`
-   - `git push`
-   - `git branch -d release-x.y.z`
+   - not sure how to do this yet
 
-- update github pages:
+- prepare for blessed Apache version
 
-   - `git checkout gh_pages`
-   - `cp -r ~/Projects/weinre/weinre.build/out/web/doc/* .` (or whatever)
-   - `git add .`
-   - `git commit -m update for release x.y.z`
-   - `git push`
-
-- announce to the world!
+   - not sure how to do this yet
 
 
 smoke test
 ===============================================================================
 
-The smoke test involves testing the three archives:
+The smoke test involves testing the archives:
 
 - `weinre-doc.zip`
-- `weinre-mac.zip`
-- `weinre-jar.zip`
+- `weinre-node.zip`
 
 
 smoke test - doc
@@ -89,28 +75,12 @@
 - browse all pages
 
 
-smoke test - mac
+smoke test - node
 -------------------------------------------------------------------------------
 
-- unzip `weinre-mac.zip`
+- unzip `weinre-node.zip`
 - make sure `build-info.txt` looks right
-- launch the app
-- open a new browser on [http://localhost:8081/demo/weinre-demo.html](http://localhost:8081/demo/weinre-demo.html)
+- run `weinre --help` make sure help works
+- run `weinre` make sure help works
 - poke around the demo, make sure it works
-- close app
-- start server in eclipse
-- launch the app
-- should get error about port in use
-
-smoke test - jar
--------------------------------------------------------------------------------
-
-- unzip `weinre-jar.zip`
-- make sure `build-info.txt` looks right
-- run `java -jar weinre.jar --help` make sure help works
-- run `java -jar weinre.jar` make sure help works
-- poke around the demo, make sure it works
-- kill server
-- start server in eclipse
-- run `java -jar weinre.jar` make sure help works
-- should get error about port in use
+- should add some variations on starting with used port, etc
\ No newline at end of file
diff --git a/weinre.build/package.json.template b/weinre.build/package.json.template
new file mode 100644
index 0000000..e5d1406
--- /dev/null
+++ b/weinre.build/package.json.template
@@ -0,0 +1,42 @@
+{
+  "name":              "weinre",
+  "description":       "WEb INspector REmote",
+  "author":            "apache.org",
+  "version":           "@WEINRE_VERSION@",
+  "tags":              [ "debug"],
+  "licenses":
+    [
+      {
+        "type":        "Apache 2.0",
+         "url":        "http://www.apache.org/licenses/LICENSE-2.0"
+      }
+    ],
+  "engines":
+    {
+      "node":          ">=0.6.0"
+    },
+  "directories":
+    {
+      "lib" :          "./lib"
+    },
+  "dependencies":
+    {
+      "coffee-script": "1.2.0",
+      "express":       "2.5.7",
+      "nopt":          "1.0.10",
+      "underscore":    "1.3.1"
+    },
+  "main" :             "./lib/weinre",
+  "bin":
+    {
+      "weinre":        "./bin/weinre"
+    },
+  "homepage":          "http://incubator.apache.org/callback/",
+  "bugs":              "https://issues.apache.org/jira/browse/CB",
+  "repository":
+    {
+      "type":          "git",
+      "url":           "https://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre.git"
+    }
+}
+
diff --git a/weinre.build/sample.personal.properties b/weinre.build/sample.personal.properties
index 73c2d6e..a0d1bf2 100644
--- a/weinre.build/sample.personal.properties
+++ b/weinre.build/sample.personal.properties
@@ -37,8 +37,3 @@
 #------------------------------------------------------------------------------
 USE_GROWL:    yup
 
-#------------------------------------------------------------------------------
-# Set to anything to enable compiling the Java code with Eclipse.
-# Delete or comment out to compile the Java code with javac.
-#------------------------------------------------------------------------------
-#USE_ECLIPSE:  yup
diff --git a/weinre.build/scripts/build-client-html.py b/weinre.build/scripts/build-client-html.py
index 86bb0ff..9cb3186 100644
--- a/weinre.build/scripts/build-client-html.py
+++ b/weinre.build/scripts/build-client-html.py
@@ -64,7 +64,7 @@
                 '<title>weinre</title>\n',
                 '<script type="text/javascript" src="weinre/check-for-webkit.js"></script>\n',
                 '<script type="text/javascript" src="weinre/hacks.js"></script>\n',
-                '<script type="text/javascript" src="../modjewel-require.js"></script>\n',
+                '<script type="text/javascript" src="../modjewel.js"></script>\n',
                 '<script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>\n',
             ])
 
diff --git a/weinre.build/scripts/build-target-scripts.py b/weinre.build/scripts/build-target-scripts.py
index 721ea26..71792b0 100644
--- a/weinre.build/scripts/build-target-scripts.py
+++ b/weinre.build/scripts/build-target-scripts.py
@@ -47,7 +47,7 @@
     scriptMin   = {}
 
     includedFiles = []
-    includedFiles.append("modjewel-require.js")
+    includedFiles.append("modjewel.js")
 
     entries = os.listdir(os.path.join(srcDirName, "weinre/common"))
     for entry in entries:
@@ -100,7 +100,7 @@
             src = "%s\n//@ sourceURL=%s" % (src, srcName)
             lines.append(";eval(%s)" % json.dumps(src))
 
-        if srcName == "modjewel-require.js":
+        if srcName == "modjewel.js":
             lines.append("require('modjewel').warnOnRecursiveRequire(true);")
             if not useEval:
                 lines.append("")
diff --git a/weinre.build/scripts/changelog.sh b/weinre.build/scripts/changelog.sh
deleted file mode 100755
index 8c7393a..0000000
--- a/weinre.build/scripts/changelog.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#/bin/sh
-
-# ---
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-# ---
-
-git log "--pretty=format:- %s" $1.. | \
-    sed 's/#\([0-9]*\)/\<a href="https:\/\/github.com\/phonegap\/weinre\/issues\/1"\>issue \1\<\/a\>./' |
-    sed 's/^-/\<li\>/'
-
-#    sed 's/#\([0-9]*\)/[issue \1](https:\/\/github.com\/pmuellr\/weinre\/issues\/1)./'
diff --git a/weinre.build/scripts/closed-issues.py b/weinre.build/scripts/closed-issues.py
deleted file mode 100755
index 4fe32de..0000000
--- a/weinre.build/scripts/closed-issues.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python
-
-# ---
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-# ---
-
-import os
-import sys
-import json
-import httplib
-
-if len(sys.argv) < 3:
-    print "expecting parameters <user> <project>"
-    sys.exit()
-
-user = sys.argv[1]
-proj = sys.argv[2]
-
-url = "/api/v2/json/issues/list/%s/%s/closed" % (user, proj)
-
-conn = httplib.HTTPConnection("github.com")
-conn.request("GET", url)
-resp = conn.getresponse()
-resp = json.loads(resp.read())
-conn.close()
-
-issues = resp["issues"]
-
-issues.sort(lambda x,y: cmp(x["number"], y["number"]))
-
-for issue in issues:
-    number = issue["number"]
-    title  = issue["title"]
-    date   = issue["closed_at"]
-
-    template = "<li><a href='https://github.com/%s/%s/issues/%d'>issue %d</a> %s - %s"
-    print template % (user, proj, number, number, date, title)
\ No newline at end of file
diff --git a/weinre.build/scripts/module2amd.py b/weinre.build/scripts/module2amd.py
new file mode 100644
index 0000000..c7e7cd3
--- /dev/null
+++ b/weinre.build/scripts/module2amd.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+
+# ---
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# ---
+
+import os
+import sys
+import optparse
+
+PROGRAM = os.path.basename(sys.argv[0])
+VERSION = "1.2.0"
+
+OutDir              = "."
+Quiet               = False
+AMDExtension        = ".amd.js"
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+def main():
+    global OutDir
+    global Quiet
+
+    usage        = "usage: %s [options] inDir inDir ..." % PROGRAM
+    version      = "%s %s" % (PROGRAM,VERSION)
+    description  = """
+Converts .js files in the inDir directories to AMD format.  See:
+http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition for more
+info.  Each inDir is considered a 'root' directory for generating
+relative module names.
+""".strip()
+    parser = optparse.OptionParser(usage=usage, version=version, description=description)
+
+    parser.add_option("-o", "--out", dest="dirName", metavar = "DIR",
+        help="generate AMD files in DIR (default: %default)"
+    )
+
+    parser.add_option("--htmlFile", dest="htmlFile", metavar = "FILE",
+        help="generate an test driver for HTML in FILE"
+    )
+
+    parser.add_option("--htmlMain", dest="htmlMain", metavar = "CODE",
+        help="a line of code to start the test driver for HTML"
+    )
+
+    parser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=Quiet,
+        help="be quiet"
+    )
+
+    parser.set_defaults(dirName=OutDir)
+
+    (options, args) = parser.parse_args()
+
+    OutDir = options.dirName
+    Quiet  = options.quiet
+
+    help = False
+    if len(args) == 0:   help = True
+    elif args[0] == "?": help = True
+
+    if help:
+        parser.print_help()
+        sys.exit(0)
+
+    htmlFile = options.htmlFile
+    htmlMain = options.htmlMain
+
+    if htmlFile and not htmlMain: error("--htmlFile specified but not --htmlMain")
+    if htmlMain and not htmlFile: error("--htmlMain specified but not --htmlFile")
+
+    for dir in args:
+        modules = processDir(dir)
+
+    if not htmlFile and not htmlMain: return
+
+    contents = []
+
+    contents.append("<script src='modjewel.js'></script>")
+    contents.append("")
+
+    for module in modules:
+        contents.append("<script src='%s%s'></script>" % (module, AMDExtension))
+
+    contents.append("")
+    contents.append("<script>")
+    contents.append(htmlMain)
+    contents.append("</script>")
+    contents.append("")
+    contents.append("<h1>check the console for test results</h1>")
+
+    htmlFileName = os.path.join(OutDir, htmlFile)
+
+    htmlFile = file(htmlFileName, "w")
+    htmlFile.write("\n".join(contents))
+    htmlFile.close()
+
+    log("generated test driver: %s" % htmlFileName)
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+def processDir(dir, path=None, modules=None):
+    if path    is None: path = []
+    if modules is None: modules = []
+
+    if not os.path.exists(dir): error("directory does not exist: %s" % dir)
+    if not os.path.isdir(dir): error("path is not directory: %s" % dir)
+
+    entries = os.listdir(dir)
+
+    for entry in entries:
+        fullEntry = os.path.join(dir, entry)
+
+        if os.path.isdir(fullEntry):
+            processDir(fullEntry, path + [entry], modules)
+            continue
+
+        if not os.path.isfile(fullEntry):           continue
+        if     entry.endswith(AMDExtension):        continue
+        if not entry.endswith(".js"):               continue
+
+        baseName  = entry[:-3]
+        iFileName = fullEntry
+        oDir      = "/".join(path)
+        oFileName = os.path.join(OutDir, oDir, baseName)
+        oFileName = "%s%s" % (oFileName, AMDExtension)
+
+        if False:
+            print "processing:   %s" % fullEntry
+            print "   oFileName: %s" % oFileName
+            continue
+
+        iFile = file(iFileName)
+        contents = iFile.read()
+        iFile.close()
+
+        if contents.startswith("#!"): contents = "// " + contents
+
+        moduleName = "%s/%s" % ("/".join(path), baseName)
+        moduleName = moduleName.lstrip("/")
+
+        modules.append(moduleName)
+
+        header  = ';define("%s", function(require, exports, module) {' % moduleName
+        trailer = '});'
+
+        newContents = "%s %s\n%s\n" % (header, contents, trailer)
+
+
+        oDirName = os.path.dirname(oFileName)
+        if os.path.exists(oDirName):
+            if not os.path.isdir(oDirName):
+                error("trying to generate a file in '%s' which isn't a directory" % oDirName)
+
+        if not os.path.exists(oDirName):
+            try:
+                os.makedirs(oDirName)
+            except:
+                error("error creating output directory '%s'" % oDirName)
+
+        oFile = file(oFileName, "w")
+        oFile.write(newContents)
+        oFile.close()
+
+        log("generated: %s" % oFileName)
+
+    return modules
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+def log(message):
+    if Quiet: return
+    print "%s: %s" % (PROGRAM, message)
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+def error(message):
+    print "%s: %s" % (PROGRAM, message)
+    exit(1)
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+def errorException(message):
+    eType  = str(sys.exc_info()[0])
+    eValue = str(sys.exc_info()[1])
+
+    error("%s; exception: %s: %s" % (message, eType, eValue))
+
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/weinre.build/update-vendor.xml b/weinre.build/update-vendor.xml
new file mode 100644
index 0000000..a6981fb
--- /dev/null
+++ b/weinre.build/update-vendor.xml
@@ -0,0 +1,97 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+-->
+
+<project name="update-vendor" default="update-vendor" basedir=".">
+
+    <property file="personal.properties"/>
+    <property file="build.properties"/>
+    <property file="vendor.properties"/>
+
+    <!-- ============================================================ -->
+
+    <target name="update-vendor">
+        <delete dir="${TMP}"/>
+
+        <delete dir="${VENDOR}"/>
+        <mkdir  dir="${VENDOR}"/>
+
+        <antcall target="get-coffeescript"/>
+        <antcall target="get-web-inspector"/>
+    </target>
+
+    <!-- ============================================================ -->
+
+    <target name="get-coffeescript">
+        <echo message="coffee-script@${COFFEESCRIPT_VERSION}"/>
+        <exec executable="npm" dir="${VENDOR}">
+            <arg value="install"/>
+            <arg value="coffee-script@${COFFEESCRIPT_VERSION}"/>
+        </exec>
+    </target>
+
+    <!-- ============================================================ -->
+
+    <target name="get-web-inspector">
+        <delete dir="${VENDOR}/webkit"/>
+        <mkdir  dir="${VENDOR}/webkit/WebCore"/>
+
+        <exec executable="svn" dir="${VENDOR}/webkit/WebCore">
+            <arg value="--non-interactive"/>
+            <arg value="--trust-server-cert"/>
+            <arg value="export"/>
+            <arg value="-r"/>
+            <arg value="${WEBKIT_VERSION}"/>
+            <arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/inspector"/>
+        </exec>
+
+        <exec executable="svn" dir="${VENDOR}/webkit/WebCore">
+            <arg value="--non-interactive"/>
+            <arg value="--trust-server-cert"/>
+            <arg value="export"/>
+            <arg value="-r"/>
+            <arg value="${WEBKIT_VERSION}"/>
+            <arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/English.lproj"/>
+        </exec>
+
+        <delete>
+            <fileset dir="${VENDOR}/webkit/WebCore/inspector">
+                <include name="**/*.cpp"/>
+                <include name="**/*.h"/>
+                <include name="**/*.pm"/>
+                <include name="**/*.pl"/>
+            </fileset>
+        </delete>
+
+        <exec executable="grep" outputproperty="gpl-grep-results" dir="${VENDOR}/webkit/WebCore">
+            <arg value="-r"/>
+            <arg value="GPL"/>
+            <arg value="."/>
+        </exec>
+
+        <condition property="found-no-gpl-files">
+            <equals arg1="" arg2="${gpl-grep-results}"/>
+        </condition>
+
+        <fail unless="found-no-gpl-files" message="The string GPL was found in the WebKit files"/>
+
+    </target>
+
+    <!-- ============================================================ -->
+
+</project>
diff --git a/weinre.build/vendor.properties b/weinre.build/vendor.properties
index f54545f..f5dce22 100644
--- a/weinre.build/vendor.properties
+++ b/weinre.build/vendor.properties
@@ -18,7 +18,7 @@
 # ---
 
 #-----------------------------------------------------------
-# location of WebKit Web Inspector
+# version / location of WebKit Web Inspector
 #-----------------------------------------------------------
 
 #WEBKIT_VERSION:         r67358
@@ -30,73 +30,7 @@
 WEBKIT_URL_PREFIX:       https://svn.webkit.org/repository/webkit/trunk
 
 #-----------------------------------------------------------
-# location of Apache Commons CLI
-#-----------------------------------------------------------
-
-CLI_VERSION:    1.2
-CLI_URL_PREFIX: http://www.apache.org/dist/commons/cli/
-
-CLI_URL:        ${CLI_URL_PREFIX}/binaries/commons-cli-${CLI_VERSION}-bin.zip
-CLI_BASENAME:   commons-cli-${CLI_VERSION}/commons-cli-${CLI_VERSION}
-
-#-----------------------------------------------------------
-# location of JSON4J
-#-----------------------------------------------------------
-
-JSON4J_VERSION:    1.1.2-incubating
-JSON4J_URL_PREFIX: http://archive.apache.org/dist/incubator/wink/
-
-JSON4J_BIN_URL:    ${JSON4J_URL_PREFIX}/${JSON4J_VERSION}/apache-wink-${JSON4J_VERSION}.zip
-JSON4J_SRC_URL:    ${JSON4J_URL_PREFIX}/${JSON4J_VERSION}/apache-wink-${JSON4J_VERSION}-src.zip
-
-#-----------------------------------------------------------
-# location of Eclipse Jetty
-#-----------------------------------------------------------
-
-JETTY_VERSION:              7.1.6.v20100715
-JETTY_URL_PREFIX:           https://oss.sonatype.org/content/groups/jetty/org/eclipse/jetty/
-
-JETTY_SRC_JAR_NAME:         jetty-all-server-${JETTY_VERSION}-sources.jar
-JETTY_SRC_URL:              ${JETTY_URL_PREFIX}/aggregate/jetty-all-server/${JETTY_VERSION}/${JETTY_SRC_JAR_NAME}
-
-JETTY_BIN_JAR_NAME:         jetty-all-server-${JETTY_VERSION}.jar
-JETTY_BIN_URL:              ${JETTY_URL_PREFIX}/aggregate/jetty-all-server/${JETTY_VERSION}/${JETTY_BIN_JAR_NAME}
-
-#-----------------------------------------------------------
-# location of servlet API
-#-----------------------------------------------------------
-
-JAVAX_SERVLET_VERSION:      2.5-20110124
-JAVAX_SERVLET_VERSION_IMPL: 6.1H.8
-JAVAX_SERVLET_URL_PREFIX:   https://oss.sonatype.org/content/groups/jetty/org/mortbay/jetty/servlet-api/
-
-JAVAX_SERVLET_JAR_NAME:     servlet-api-${JAVAX_SERVLET_VERSION}.jar
-JAVAX_SERVLET_URL:          ${JAVAX_SERVLET_URL_PREFIX}/${JAVAX_SERVLET_VERSION}/${JAVAX_SERVLET_JAR_NAME}
-
-#-----------------------------------------------------------
-# location of Eclipse SWT
-#-----------------------------------------------------------
-
-SWT_VERSION_MAJOR: 3.6
-SWT_VERSION:       ${SWT_VERSION_MAJOR}-201006080911
-SWT_URL_PREFIX:    http://archive.eclipse.org/eclipse/downloads/drops/R-${SWT_VERSION}
-
-#-----------------------------------------------------------
-# location of CoffeeScript
+# version of CoffeeScript
 #-----------------------------------------------------------
 
 COFFEESCRIPT_VERSION:    1.1.2
-
-#-----------------------------------------------------------
-# location of json2
-#-----------------------------------------------------------
-
-JSON2_VERSION:    8e0b15cb492f63067a88ad786e4d5fc0fa89a241
-JSON2_URL_PREFIX: https://github.com/douglascrockford/JSON-js/raw/${JSON2_VERSION}
-
-#-----------------------------------------------------------
-# location of modjewel
-#-----------------------------------------------------------
-
-MODJEWEL_VERSION:    48f3eb797850e5ab3e2132b19a1db4797559efe7
-MODJEWEL_URL_PREFIX: https://github.com/pmuellr/modjewel/raw/${MODJEWEL_VERSION}
diff --git a/weinre.build/vendor/node_modules/.bin/cake b/weinre.build/vendor/node_modules/.bin/cake
new file mode 120000
index 0000000..d95f32a
--- /dev/null
+++ b/weinre.build/vendor/node_modules/.bin/cake
@@ -0,0 +1 @@
+../coffee-script/bin/cake
\ No newline at end of file
diff --git a/weinre.build/vendor/node_modules/.bin/coffee b/weinre.build/vendor/node_modules/.bin/coffee
new file mode 120000
index 0000000..b57f275
--- /dev/null
+++ b/weinre.build/vendor/node_modules/.bin/coffee
@@ -0,0 +1 @@
+../coffee-script/bin/coffee
\ No newline at end of file
diff --git a/weinre.build/vendor/node_modules/coffee-script/.npmignore b/weinre.build/vendor/node_modules/coffee-script/.npmignore
new file mode 100644
index 0000000..21e430d
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/.npmignore
@@ -0,0 +1,11 @@
+*.coffee
+*.html
+.DS_Store
+.git*
+Cakefile
+documentation/
+examples/
+extras/coffee-script.js
+raw/
+src/
+test/
diff --git a/weinre.build/vendor/node_modules/coffee-script/LICENSE b/weinre.build/vendor/node_modules/coffee-script/LICENSE
new file mode 100644
index 0000000..8cb3cfd
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Jeremy Ashkenas
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.build/vendor/node_modules/coffee-script/README b/weinre.build/vendor/node_modules/coffee-script/README
new file mode 100644
index 0000000..08f17df
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/README
@@ -0,0 +1,48 @@
+=
+            {
+         }   }   {
+        {   {  }  }
+         }   }{  {
+        {  }{  }  }                    _____       __  __
+       ( }{ }{  { )                   / ____|     / _|/ _|
+     .- { { }  { }} -.               | |     ___ | |_| |_ ___  ___
+    (  ( } { } { } }  )              | |    / _ \|  _|  _/ _ \/ _ \
+    |`-..________ ..-'|              | |___| (_) | | | ||  __/  __/
+    |                 |               \_____\___/|_| |_| \___|\___|
+    |                 ;--.
+    |                (__  \            _____           _       _
+    |                 | )  )          / ____|         (_)     | |
+    |                 |/  /          | (___   ___ _ __ _ _ __ | |_
+    |                 (  /            \___ \ / __| '__| | '_ \| __|
+    |                 |/              ____) | (__| |  | | |_) | |_
+    |                 |              |_____/ \___|_|  |_| .__/ \__|
+     `-.._________..-'                                  | |
+                                                        |_|
+
+
+  CoffeeScript is a little language that compiles into JavaScript.
+
+  Install Node.js, and then the CoffeeScript compiler:
+  sudo bin/cake install
+
+  Or, if you have the Node Package Manager installed:
+  npm install -g coffee-script
+  (Leave off the -g if you don't wish to install globally.)
+
+  Compile a script:
+  coffee /path/to/script.coffee
+
+  For documentation, usage, and examples, see:
+  http://coffeescript.org/
+
+  To suggest a feature, report a bug, or general discussion:
+  http://github.com/jashkenas/coffee-script/issues/
+
+  If you'd like to chat, drop by #coffeescript on Freenode IRC,
+  or on webchat.freenode.net.
+
+  The source repository:
+  git://github.com/jashkenas/coffee-script.git
+
+  All contributors are listed here:
+  http://github.com/jashkenas/coffee-script/contributors
diff --git a/weinre.build/vendor/node_modules/coffee-script/Rakefile b/weinre.build/vendor/node_modules/coffee-script/Rakefile
new file mode 100644
index 0000000..dfb85da
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/Rakefile
@@ -0,0 +1,78 @@
+require 'rubygems'
+require 'erb'
+require 'fileutils'
+require 'rake/testtask'
+require 'json'
+
+desc "Build the documentation page"
+task :doc do
+  source = 'documentation/index.html.erb'
+  child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
+  at_exit { Process.kill("INT", child) }
+  Signal.trap("INT") { exit }
+  loop do
+    mtime = File.stat(source).mtime
+    if !@mtime || mtime > @mtime
+      rendered = ERB.new(File.read(source)).result(binding)
+      File.open('index.html', 'w+') {|f| f.write(rendered) }
+    end
+    @mtime = mtime
+    sleep 1
+  end
+end
+
+desc "Build coffee-script-source gem"
+task :gem do
+  require 'rubygems'
+  require 'rubygems/package'
+
+  gemspec = Gem::Specification.new do |s|
+    s.name      = 'coffee-script-source'
+    s.version   = JSON.parse(File.read('package.json'))["version"]
+    s.date      = Time.now.strftime("%Y-%m-%d")
+
+    s.homepage    = "http://jashkenas.github.com/coffee-script/"
+    s.summary     = "The CoffeeScript Compiler"
+    s.description = <<-EOS
+      CoffeeScript is a little language that compiles into JavaScript.
+      Underneath all of those embarrassing braces and semicolons,
+      JavaScript has always had a gorgeous object model at its heart.
+      CoffeeScript is an attempt to expose the good parts of JavaScript
+      in a simple way.
+    EOS
+
+    s.files = [
+      'lib/coffee_script/coffee-script.js',
+      'lib/coffee_script/source.rb'
+    ]
+
+    s.authors           = ['Jeremy Ashkenas']
+    s.email             = 'jashkenas@gmail.com'
+    s.rubyforge_project = 'coffee-script-source'
+  end
+
+  file = File.open("coffee-script-source.gem", "w")
+  Gem::Package.open(file, 'w') do |pkg|
+    pkg.metadata = gemspec.to_yaml
+
+    path = "lib/coffee_script/source.rb"
+    contents = <<-ERUBY
+module CoffeeScript
+  module Source
+    def self.bundled_path
+      File.expand_path("../coffee-script.js", __FILE__)
+    end
+  end
+end
+    ERUBY
+    pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+      tar_io.write(contents)
+    end
+
+    contents = File.read("extras/coffee-script.js")
+    path = "lib/coffee_script/coffee-script.js"
+    pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+      tar_io.write(contents)
+    end
+  end
+end
diff --git a/weinre.build/vendor/node_modules/coffee-script/extras/jsl.conf b/weinre.build/vendor/node_modules/coffee-script/extras/jsl.conf
new file mode 100644
index 0000000..1190da5
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/extras/jsl.conf
@@ -0,0 +1,44 @@
+# JavaScriptLint configuration file for CoffeeScript.
+
++no_return_value              # function {0} does not always return a value
++duplicate_formal             # duplicate formal argument {0}
+-equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg                # variable {0} hides argument
++redeclared_var               # redeclaration of {0} {1}
+-anon_no_return_value         # anonymous function does not always return a value
++missing_semicolon            # missing semicolon
++meaningless_block            # meaningless block; curly braces have no impact
+-comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
++unreachable_code             # unreachable code
++missing_break                # missing break statement
+-missing_break_for_last_case  # missing break statement for last case in switch
+-comparison_type_conv         # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+-inc_dec_within_stmt          # increment (++) and decrement (--) operators used as part of greater statement
+-useless_void                 # use of the void type may be unnecessary (void is always undefined)
++multiple_plus_minus          # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label                 # use of label
+-block_without_braces         # block statement without curly braces
++leading_decimal_point        # leading decimal point may indicate a number or an object member
++trailing_decimal_point       # trailing decimal point may indicate a number or an object member
++octal_number                 # leading zeros make an octal number
++nested_comment               # nested comment
++misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
++ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement              # empty statement or extra semicolon
+-missing_option_explicit      # the "option explicit" control comment is missing
++partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit          # duplicate "option explicit" control comment
++useless_assign               # useless assignment
++ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+-missing_default_case         # missing default case in switch statement
++duplicate_case_in_switch     # duplicate case in switch statements
++default_not_at_end           # the default case is not at the end of the switch statement
++legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison           # useless comparison; comparing identical expressions
++with_statement               # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array      # extra comma is not recommended in array initializers
++assign_to_function_call      # assignment to a function call
++parseint_missing_radix       # parseInt missing radix parameter
++lambda_assign_requires_semicolon
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/browser.js b/weinre.build/vendor/node_modules/coffee-script/lib/browser.js
new file mode 100644
index 0000000..2fb7b2e
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/browser.js
@@ -0,0 +1,75 @@
+(function() {
+  var CoffeeScript, runScripts;
+  CoffeeScript = require('./coffee-script');
+  CoffeeScript.require = require;
+  CoffeeScript.eval = function(code, options) {
+    return eval(CoffeeScript.compile(code, options));
+  };
+  CoffeeScript.run = function(code, options) {
+    if (options == null) {
+      options = {};
+    }
+    options.bare = true;
+    return Function(CoffeeScript.compile(code, options))();
+  };
+  if (typeof window === "undefined" || window === null) {
+    return;
+  }
+  CoffeeScript.load = function(url, callback) {
+    var xhr;
+    xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
+    xhr.open('GET', url, true);
+    if ('overrideMimeType' in xhr) {
+      xhr.overrideMimeType('text/plain');
+    }
+    xhr.onreadystatechange = function() {
+      var _ref;
+      if (xhr.readyState === 4) {
+        if ((_ref = xhr.status) === 0 || _ref === 200) {
+          CoffeeScript.run(xhr.responseText);
+        } else {
+          throw new Error("Could not load " + url);
+        }
+        if (callback) {
+          return callback();
+        }
+      }
+    };
+    return xhr.send(null);
+  };
+  runScripts = function() {
+    var coffees, execute, index, length, s, scripts;
+    scripts = document.getElementsByTagName('script');
+    coffees = (function() {
+      var _i, _len, _results;
+      _results = [];
+      for (_i = 0, _len = scripts.length; _i < _len; _i++) {
+        s = scripts[_i];
+        if (s.type === 'text/coffeescript') {
+          _results.push(s);
+        }
+      }
+      return _results;
+    })();
+    index = 0;
+    length = coffees.length;
+    (execute = function() {
+      var script;
+      script = coffees[index++];
+      if ((script != null ? script.type : void 0) === 'text/coffeescript') {
+        if (script.src) {
+          return CoffeeScript.load(script.src, execute);
+        } else {
+          CoffeeScript.run(script.innerHTML);
+          return execute();
+        }
+      }
+    })();
+    return null;
+  };
+  if (window.addEventListener) {
+    addEventListener('DOMContentLoaded', runScripts, false);
+  } else {
+    attachEvent('onload', runScripts);
+  }
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/cake.js b/weinre.build/vendor/node_modules/coffee-script/lib/cake.js
new file mode 100755
index 0000000..6619934
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/cake.js
@@ -0,0 +1,76 @@
+(function() {
+  var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
+  fs = require('fs');
+  path = require('path');
+  helpers = require('./helpers');
+  optparse = require('./optparse');
+  CoffeeScript = require('./coffee-script');
+  tasks = {};
+  options = {};
+  switches = [];
+  oparse = null;
+  helpers.extend(global, {
+    task: function(name, description, action) {
+      var _ref;
+      if (!action) {
+        _ref = [description, action], action = _ref[0], description = _ref[1];
+      }
+      return tasks[name] = {
+        name: name,
+        description: description,
+        action: action
+      };
+    },
+    option: function(letter, flag, description) {
+      return switches.push([letter, flag, description]);
+    },
+    invoke: function(name) {
+      if (!tasks[name]) {
+        missingTask(name);
+      }
+      return tasks[name].action(options);
+    }
+  });
+  exports.run = function() {
+    return path.exists('Cakefile', function(exists) {
+      var arg, args, _i, _len, _ref, _results;
+      if (!exists) {
+        throw new Error("Cakefile not found in " + (process.cwd()));
+      }
+      args = process.argv.slice(2);
+      CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
+        filename: 'Cakefile'
+      });
+      oparse = new optparse.OptionParser(switches);
+      if (!args.length) {
+        return printTasks();
+      }
+      options = oparse.parse(args);
+      _ref = options.arguments;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        arg = _ref[_i];
+        _results.push(invoke(arg));
+      }
+      return _results;
+    });
+  };
+  printTasks = function() {
+    var desc, name, spaces, task;
+    console.log('');
+    for (name in tasks) {
+      task = tasks[name];
+      spaces = 20 - name.length;
+      spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
+      desc = task.description ? "# " + task.description : '';
+      console.log("cake " + name + spaces + " " + desc);
+    }
+    if (switches.length) {
+      return console.log(oparse.help());
+    }
+  };
+  missingTask = function(task) {
+    console.log("No such task: \"" + task + "\"");
+    return process.exit(1);
+  };
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/coffee-script.js b/weinre.build/vendor/node_modules/coffee-script/lib/coffee-script.js
new file mode 100755
index 0000000..2871279
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/coffee-script.js
@@ -0,0 +1,135 @@
+(function() {
+  var Lexer, RESERVED, compile, fs, lexer, parser, path, _ref;
+  var __hasProp = Object.prototype.hasOwnProperty;
+  fs = require('fs');
+  path = require('path');
+  _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
+  parser = require('./parser').parser;
+  if (require.extensions) {
+    require.extensions['.coffee'] = function(module, filename) {
+      var content;
+      content = compile(fs.readFileSync(filename, 'utf8'), {
+        filename: filename
+      });
+      return module._compile(content, filename);
+    };
+  } else if (require.registerExtension) {
+    require.registerExtension('.coffee', function(content) {
+      return compile(content);
+    });
+  }
+  exports.VERSION = '1.1.2';
+  exports.RESERVED = RESERVED;
+  exports.helpers = require('./helpers');
+  exports.compile = compile = function(code, options) {
+    if (options == null) {
+      options = {};
+    }
+    try {
+      return (parser.parse(lexer.tokenize(code))).compile(options);
+    } catch (err) {
+      if (options.filename) {
+        err.message = "In " + options.filename + ", " + err.message;
+      }
+      throw err;
+    }
+  };
+  exports.tokens = function(code, options) {
+    return lexer.tokenize(code, options);
+  };
+  exports.nodes = function(source, options) {
+    if (typeof source === 'string') {
+      return parser.parse(lexer.tokenize(source, options));
+    } else {
+      return parser.parse(source);
+    }
+  };
+  exports.run = function(code, options) {
+    var Module, mainModule;
+    mainModule = require.main;
+    mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
+    mainModule.moduleCache && (mainModule.moduleCache = {});
+    if (process.binding('natives').module) {
+      Module = require('module').Module;
+      mainModule.paths = Module._nodeModulePaths(path.dirname(options.filename));
+    }
+    if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
+      return mainModule._compile(compile(code, options), mainModule.filename);
+    } else {
+      return mainModule._compile(code, mainModule.filename);
+    }
+  };
+  exports.eval = function(code, options) {
+    var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _ref4, _require;
+    if (options == null) {
+      options = {};
+    }
+    if (!(code = code.trim())) {
+      return;
+    }
+    if (_ref2 = require('vm'), Script = _ref2.Script, _ref2) {
+      sandbox = Script.createContext();
+      sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
+      if (options.sandbox != null) {
+        if (options.sandbox instanceof sandbox.constructor) {
+          sandbox = options.sandbox;
+        } else {
+          _ref3 = options.sandbox;
+          for (k in _ref3) {
+            if (!__hasProp.call(_ref3, k)) continue;
+            v = _ref3[k];
+            sandbox[k] = v;
+          }
+        }
+      }
+      sandbox.__filename = options.filename || 'eval';
+      sandbox.__dirname = path.dirname(sandbox.__filename);
+      if (!(sandbox.module || sandbox.require)) {
+        Module = require('module');
+        sandbox.module = _module = new Module(options.modulename || 'eval');
+        sandbox.require = _require = function(path) {
+          return Module._load(path, _module);
+        };
+        _module.filename = sandbox.__filename;
+        _ref4 = Object.getOwnPropertyNames(require);
+        for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
+          r = _ref4[_i];
+          _require[r] = require[r];
+        }
+        _require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
+        _require.resolve = function(request) {
+          return Module._resolveFilename(request, _module);
+        };
+      }
+    }
+    o = {};
+    for (k in options) {
+      if (!__hasProp.call(options, k)) continue;
+      v = options[k];
+      o[k] = v;
+    }
+    o.bare = true;
+    js = compile(code, o);
+    if (Script) {
+      return Script.runInContext(js, sandbox);
+    } else {
+      return eval(js);
+    }
+  };
+  lexer = new Lexer;
+  parser.lexer = {
+    lex: function() {
+      var tag, _ref2;
+      _ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
+      return tag;
+    },
+    setInput: function(tokens) {
+      this.tokens = tokens;
+      return this.pos = 0;
+    },
+    upcomingInput: function() {
+      return "";
+    }
+  };
+  parser.yy = require('./nodes');
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/command.js b/weinre.build/vendor/node_modules/coffee-script/lib/command.js
new file mode 100644
index 0000000..ca25502
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/command.js
@@ -0,0 +1,301 @@
+(function() {
+  var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compileScript, compileScripts, compileStdio, contents, exec, forkNode, fs, helpers, lint, loadRequires, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, version, watch, writeJs, _ref;
+  fs = require('fs');
+  path = require('path');
+  helpers = require('./helpers');
+  optparse = require('./optparse');
+  CoffeeScript = require('./coffee-script');
+  _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
+  EventEmitter = require('events').EventEmitter;
+  helpers.extend(CoffeeScript, new EventEmitter);
+  printLine = function(line) {
+    return process.stdout.write(line + '\n');
+  };
+  printWarn = function(line) {
+    return process.binding('stdio').writeError(line + '\n');
+  };
+  BANNER = 'Usage: coffee [options] path/to/script.coffee';
+  SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
+  opts = {};
+  sources = [];
+  contents = [];
+  optionParser = null;
+  exports.run = function() {
+    parseOptions();
+    if (opts.nodejs) {
+      return forkNode();
+    }
+    if (opts.help) {
+      return usage();
+    }
+    if (opts.version) {
+      return version();
+    }
+    if (opts.require) {
+      loadRequires();
+    }
+    if (opts.interactive) {
+      return require('./repl');
+    }
+    if (opts.stdio) {
+      return compileStdio();
+    }
+    if (opts.eval) {
+      return compileScript(null, sources[0]);
+    }
+    if (!sources.length) {
+      return require('./repl');
+    }
+    if (opts.run) {
+      opts.literals = sources.splice(1).concat(opts.literals);
+    }
+    process.ARGV = process.argv = process.argv.slice(0, 2).concat(opts.literals);
+    process.argv[0] = 'coffee';
+    process.execPath = require.main.filename;
+    return compileScripts();
+  };
+  compileScripts = function() {
+    var base, compile, source, unprocessed, _i, _j, _len, _len2, _results;
+    unprocessed = [];
+    for (_i = 0, _len = sources.length; _i < _len; _i++) {
+      source = sources[_i];
+      unprocessed[sources.indexOf(source)] = 1;
+    }
+    _results = [];
+    for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
+      source = sources[_j];
+      base = path.join(source);
+      compile = function(source, sourceIndex, topLevel) {
+        var remaining_files;
+        remaining_files = function() {
+          var total, x, _k, _len3;
+          total = 0;
+          for (_k = 0, _len3 = unprocessed.length; _k < _len3; _k++) {
+            x = unprocessed[_k];
+            total += x;
+          }
+          return total;
+        };
+        return path.exists(source, function(exists) {
+          if (topLevel && !exists && source.slice(-7) !== '.coffee') {
+            return compile("" + source + ".coffee", sourceIndex, topLevel);
+          }
+          if (topLevel && !exists) {
+            throw new Error("File not found: " + source);
+          }
+          return fs.stat(source, function(err, stats) {
+            if (err) {
+              throw err;
+            }
+            if (stats.isDirectory()) {
+              return fs.readdir(source, function(err, files) {
+                var file, _k, _len3;
+                if (err) {
+                  throw err;
+                }
+                unprocessed[sourceIndex] += files.length;
+                for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
+                  file = files[_k];
+                  compile(path.join(source, file), sourceIndex);
+                }
+                return unprocessed[sourceIndex] -= 1;
+              });
+            } else if (topLevel || path.extname(source) === '.coffee') {
+              fs.readFile(source, function(err, code) {
+                if (err) {
+                  throw err;
+                }
+                unprocessed[sourceIndex] -= 1;
+                if (opts.join) {
+                  contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
+                  if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
+                    return compileJoin();
+                  }
+                } else {
+                  return compileScript(source, code.toString(), base);
+                }
+              });
+              if (opts.watch && !opts.join) {
+                return watch(source, base);
+              }
+            } else {
+              return unprocessed[sourceIndex] -= 1;
+            }
+          });
+        });
+      };
+      _results.push(compile(source, sources.indexOf(source), true));
+    }
+    return _results;
+  };
+  compileScript = function(file, input, base) {
+    var o, options, t, task;
+    o = opts;
+    options = compileOptions(file);
+    try {
+      t = task = {
+        file: file,
+        input: input,
+        options: options
+      };
+      CoffeeScript.emit('compile', task);
+      if (o.tokens) {
+        return printTokens(CoffeeScript.tokens(t.input));
+      } else if (o.nodes) {
+        return printLine(CoffeeScript.nodes(t.input).toString().trim());
+      } else if (o.run) {
+        return CoffeeScript.run(t.input, t.options);
+      } else {
+        t.output = CoffeeScript.compile(t.input, t.options);
+        CoffeeScript.emit('success', task);
+        if (o.print) {
+          return printLine(t.output.trim());
+        } else if (o.compile) {
+          return writeJs(t.file, t.output, base);
+        } else if (o.lint) {
+          return lint(t.file, t.output);
+        }
+      }
+    } catch (err) {
+      CoffeeScript.emit('failure', err, task);
+      if (CoffeeScript.listeners('failure').length) {
+        return;
+      }
+      if (o.watch) {
+        return printLine(err.message);
+      }
+      printWarn(err.stack);
+      return process.exit(1);
+    }
+  };
+  compileStdio = function() {
+    var code, stdin;
+    code = '';
+    stdin = process.openStdin();
+    stdin.on('data', function(buffer) {
+      if (buffer) {
+        return code += buffer.toString();
+      }
+    });
+    return stdin.on('end', function() {
+      return compileScript(null, code);
+    });
+  };
+  compileJoin = function() {
+    var code;
+    code = contents.join('\n');
+    return compileScript(opts.join, code, opts.join);
+  };
+  loadRequires = function() {
+    var realFilename, req, _i, _len, _ref2;
+    realFilename = module.filename;
+    module.filename = '.';
+    _ref2 = opts.require;
+    for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+      req = _ref2[_i];
+      require(req);
+    }
+    return module.filename = realFilename;
+  };
+  watch = function(source, base) {
+    return fs.watchFile(source, {
+      persistent: true,
+      interval: 500
+    }, function(curr, prev) {
+      if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
+        return;
+      }
+      return fs.readFile(source, function(err, code) {
+        if (err) {
+          throw err;
+        }
+        return compileScript(source, code.toString(), base);
+      });
+    });
+  };
+  writeJs = function(source, js, base) {
+    var baseDir, compile, dir, filename, jsPath, srcDir;
+    filename = path.basename(source, path.extname(source)) + '.js';
+    srcDir = path.dirname(source);
+    baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
+    dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
+    jsPath = path.join(dir, filename);
+    compile = function() {
+      if (js.length <= 0) {
+        js = ' ';
+      }
+      return fs.writeFile(jsPath, js, function(err) {
+        if (err) {
+          return printLine(err.message);
+        } else if (opts.compile && opts.watch) {
+          return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
+        }
+      });
+    };
+    return path.exists(dir, function(exists) {
+      if (exists) {
+        return compile();
+      } else {
+        return exec("mkdir -p " + dir, compile);
+      }
+    });
+  };
+  lint = function(file, js) {
+    var conf, jsl, printIt;
+    printIt = function(buffer) {
+      return printLine(file + ':\t' + buffer.toString().trim());
+    };
+    conf = __dirname + '/../extras/jsl.conf';
+    jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
+    jsl.stdout.on('data', printIt);
+    jsl.stderr.on('data', printIt);
+    jsl.stdin.write(js);
+    return jsl.stdin.end();
+  };
+  printTokens = function(tokens) {
+    var strings, tag, token, value;
+    strings = (function() {
+      var _i, _len, _ref2, _results;
+      _results = [];
+      for (_i = 0, _len = tokens.length; _i < _len; _i++) {
+        token = tokens[_i];
+        _ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
+        _results.push("[" + tag + " " + value + "]");
+      }
+      return _results;
+    })();
+    return printLine(strings.join(' '));
+  };
+  parseOptions = function() {
+    var o;
+    optionParser = new optparse.OptionParser(SWITCHES, BANNER);
+    o = opts = optionParser.parse(process.argv.slice(2));
+    o.compile || (o.compile = !!o.output);
+    o.run = !(o.compile || o.print || o.lint);
+    o.print = !!(o.print || (o.eval || o.stdio && o.compile));
+    return sources = o.arguments;
+  };
+  compileOptions = function(filename) {
+    return {
+      filename: filename,
+      bare: opts.bare
+    };
+  };
+  forkNode = function() {
+    var args, nodeArgs;
+    nodeArgs = opts.nodejs.split(/\s+/);
+    args = process.argv.slice(1);
+    args.splice(args.indexOf('--nodejs'), 2);
+    return spawn(process.execPath, nodeArgs.concat(args), {
+      cwd: process.cwd(),
+      env: process.env,
+      customFds: [0, 1, 2]
+    });
+  };
+  usage = function() {
+    return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
+  };
+  version = function() {
+    return printLine("CoffeeScript version " + CoffeeScript.VERSION);
+  };
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/grammar.js b/weinre.build/vendor/node_modules/coffee-script/lib/grammar.js
new file mode 100644
index 0000000..e0bc41f
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/grammar.js
@@ -0,0 +1,591 @@
+(function() {
+  var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
+  Parser = require('jison').Parser;
+  unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
+  o = function(patternString, action, options) {
+    var match;
+    patternString = patternString.replace(/\s{2,}/g, ' ');
+    if (!action) {
+      return [patternString, '$$ = $1;', options];
+    }
+    action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
+    action = action.replace(/\bnew /g, '$&yy.');
+    action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
+    return [patternString, "$$ = " + action + ";", options];
+  };
+  grammar = {
+    Root: [
+      o('', function() {
+        return new Block;
+      }), o('Body'), o('Block TERMINATOR')
+    ],
+    Body: [
+      o('Line', function() {
+        return Block.wrap([$1]);
+      }), o('Body TERMINATOR Line', function() {
+        return $1.push($3);
+      }), o('Body TERMINATOR')
+    ],
+    Line: [o('Expression'), o('Statement')],
+    Statement: [
+      o('Return'), o('Throw'), o('Comment'), o('STATEMENT', function() {
+        return new Literal($1);
+      })
+    ],
+    Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class')],
+    Block: [
+      o('INDENT OUTDENT', function() {
+        return new Block;
+      }), o('INDENT Body OUTDENT', function() {
+        return $2;
+      })
+    ],
+    Identifier: [
+      o('IDENTIFIER', function() {
+        return new Literal($1);
+      })
+    ],
+    AlphaNumeric: [
+      o('NUMBER', function() {
+        return new Literal($1);
+      }), o('STRING', function() {
+        return new Literal($1);
+      })
+    ],
+    Literal: [
+      o('AlphaNumeric'), o('JS', function() {
+        return new Literal($1);
+      }), o('REGEX', function() {
+        return new Literal($1);
+      }), o('BOOL', function() {
+        var val;
+        val = new Literal($1);
+        if ($1 === 'undefined') {
+          val.isUndefined = true;
+        }
+        return val;
+      })
+    ],
+    Assign: [
+      o('Assignable = Expression', function() {
+        return new Assign($1, $3);
+      }), o('Assignable = INDENT Expression OUTDENT', function() {
+        return new Assign($1, $4);
+      })
+    ],
+    AssignObj: [
+      o('ObjAssignable', function() {
+        return new Value($1);
+      }), o('ObjAssignable : Expression', function() {
+        return new Assign(new Value($1), $3, 'object');
+      }), o('ObjAssignable :\
+       INDENT Expression OUTDENT', function() {
+        return new Assign(new Value($1), $4, 'object');
+      }), o('Comment')
+    ],
+    ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
+    Return: [
+      o('RETURN Expression', function() {
+        return new Return($2);
+      }), o('RETURN', function() {
+        return new Return;
+      })
+    ],
+    Comment: [
+      o('HERECOMMENT', function() {
+        return new Comment($1);
+      })
+    ],
+    Code: [
+      o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
+        return new Code($2, $5, $4);
+      }), o('FuncGlyph Block', function() {
+        return new Code([], $2, $1);
+      })
+    ],
+    FuncGlyph: [
+      o('->', function() {
+        return 'func';
+      }), o('=>', function() {
+        return 'boundfunc';
+      })
+    ],
+    OptComma: [o(''), o(',')],
+    ParamList: [
+      o('', function() {
+        return [];
+      }), o('Param', function() {
+        return [$1];
+      }), o('ParamList , Param', function() {
+        return $1.concat($3);
+      })
+    ],
+    Param: [
+      o('ParamVar', function() {
+        return new Param($1);
+      }), o('ParamVar ...', function() {
+        return new Param($1, null, true);
+      }), o('ParamVar = Expression', function() {
+        return new Param($1, $3);
+      })
+    ],
+    ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
+    Splat: [
+      o('Expression ...', function() {
+        return new Splat($1);
+      })
+    ],
+    SimpleAssignable: [
+      o('Identifier', function() {
+        return new Value($1);
+      }), o('Value Accessor', function() {
+        return $1.push($2);
+      }), o('Invocation Accessor', function() {
+        return new Value($1, [$2]);
+      }), o('ThisProperty')
+    ],
+    Assignable: [
+      o('SimpleAssignable'), o('Array', function() {
+        return new Value($1);
+      }), o('Object', function() {
+        return new Value($1);
+      })
+    ],
+    Value: [
+      o('Assignable'), o('Literal', function() {
+        return new Value($1);
+      }), o('Parenthetical', function() {
+        return new Value($1);
+      }), o('Range', function() {
+        return new Value($1);
+      }), o('This')
+    ],
+    Accessor: [
+      o('.  Identifier', function() {
+        return new Access($2);
+      }), o('?. Identifier', function() {
+        return new Access($2, 'soak');
+      }), o(':: Identifier', function() {
+        return new Access($2, 'proto');
+      }), o('::', function() {
+        return new Access(new Literal('prototype'));
+      }), o('Index')
+    ],
+    Index: [
+      o('INDEX_START IndexValue INDEX_END', function() {
+        return $2;
+      }), o('INDEX_SOAK  Index', function() {
+        return extend($2, {
+          soak: true
+        });
+      }), o('INDEX_PROTO Index', function() {
+        return extend($2, {
+          proto: true
+        });
+      })
+    ],
+    IndexValue: [
+      o('Expression', function() {
+        return new Index($1);
+      }), o('Slice', function() {
+        return new Slice($1);
+      })
+    ],
+    Object: [
+      o('{ AssignList OptComma }', function() {
+        return new Obj($2, $1.generated);
+      })
+    ],
+    AssignList: [
+      o('', function() {
+        return [];
+      }), o('AssignObj', function() {
+        return [$1];
+      }), o('AssignList , AssignObj', function() {
+        return $1.concat($3);
+      }), o('AssignList OptComma TERMINATOR AssignObj', function() {
+        return $1.concat($4);
+      }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
+        return $1.concat($4);
+      })
+    ],
+    Class: [
+      o('CLASS', function() {
+        return new Class;
+      }), o('CLASS Block', function() {
+        return new Class(null, null, $2);
+      }), o('CLASS EXTENDS Value', function() {
+        return new Class(null, $3);
+      }), o('CLASS EXTENDS Value Block', function() {
+        return new Class(null, $3, $4);
+      }), o('CLASS SimpleAssignable', function() {
+        return new Class($2);
+      }), o('CLASS SimpleAssignable Block', function() {
+        return new Class($2, null, $3);
+      }), o('CLASS SimpleAssignable EXTENDS Value', function() {
+        return new Class($2, $4);
+      }), o('CLASS SimpleAssignable EXTENDS Value Block', function() {
+        return new Class($2, $4, $5);
+      })
+    ],
+    Invocation: [
+      o('Value OptFuncExist Arguments', function() {
+        return new Call($1, $3, $2);
+      }), o('Invocation OptFuncExist Arguments', function() {
+        return new Call($1, $3, $2);
+      }), o('SUPER', function() {
+        return new Call('super', [new Splat(new Literal('arguments'))]);
+      }), o('SUPER Arguments', function() {
+        return new Call('super', $2);
+      })
+    ],
+    OptFuncExist: [
+      o('', function() {
+        return false;
+      }), o('FUNC_EXIST', function() {
+        return true;
+      })
+    ],
+    Arguments: [
+      o('CALL_START CALL_END', function() {
+        return [];
+      }), o('CALL_START ArgList OptComma CALL_END', function() {
+        return $2;
+      })
+    ],
+    This: [
+      o('THIS', function() {
+        return new Value(new Literal('this'));
+      }), o('@', function() {
+        return new Value(new Literal('this'));
+      })
+    ],
+    ThisProperty: [
+      o('@ Identifier', function() {
+        return new Value(new Literal('this'), [new Access($2)], 'this');
+      })
+    ],
+    Array: [
+      o('[ ]', function() {
+        return new Arr([]);
+      }), o('[ ArgList OptComma ]', function() {
+        return new Arr($2);
+      })
+    ],
+    RangeDots: [
+      o('..', function() {
+        return 'inclusive';
+      }), o('...', function() {
+        return 'exclusive';
+      })
+    ],
+    Range: [
+      o('[ Expression RangeDots Expression ]', function() {
+        return new Range($2, $4, $3);
+      })
+    ],
+    Slice: [
+      o('Expression RangeDots Expression', function() {
+        return new Range($1, $3, $2);
+      }), o('Expression RangeDots', function() {
+        return new Range($1, null, $2);
+      }), o('RangeDots Expression', function() {
+        return new Range(null, $2, $1);
+      })
+    ],
+    ArgList: [
+      o('Arg', function() {
+        return [$1];
+      }), o('ArgList , Arg', function() {
+        return $1.concat($3);
+      }), o('ArgList OptComma TERMINATOR Arg', function() {
+        return $1.concat($4);
+      }), o('INDENT ArgList OptComma OUTDENT', function() {
+        return $2;
+      }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
+        return $1.concat($4);
+      })
+    ],
+    Arg: [o('Expression'), o('Splat')],
+    SimpleArgs: [
+      o('Expression'), o('SimpleArgs , Expression', function() {
+        return [].concat($1, $3);
+      })
+    ],
+    Try: [
+      o('TRY Block', function() {
+        return new Try($2);
+      }), o('TRY Block Catch', function() {
+        return new Try($2, $3[0], $3[1]);
+      }), o('TRY Block FINALLY Block', function() {
+        return new Try($2, null, null, $4);
+      }), o('TRY Block Catch FINALLY Block', function() {
+        return new Try($2, $3[0], $3[1], $5);
+      })
+    ],
+    Catch: [
+      o('CATCH Identifier Block', function() {
+        return [$2, $3];
+      })
+    ],
+    Throw: [
+      o('THROW Expression', function() {
+        return new Throw($2);
+      })
+    ],
+    Parenthetical: [
+      o('( Body )', function() {
+        return new Parens($2);
+      }), o('( INDENT Body OUTDENT )', function() {
+        return new Parens($3);
+      })
+    ],
+    WhileSource: [
+      o('WHILE Expression', function() {
+        return new While($2);
+      }), o('WHILE Expression WHEN Expression', function() {
+        return new While($2, {
+          guard: $4
+        });
+      }), o('UNTIL Expression', function() {
+        return new While($2, {
+          invert: true
+        });
+      }), o('UNTIL Expression WHEN Expression', function() {
+        return new While($2, {
+          invert: true,
+          guard: $4
+        });
+      })
+    ],
+    While: [
+      o('WhileSource Block', function() {
+        return $1.addBody($2);
+      }), o('Statement  WhileSource', function() {
+        return $2.addBody(Block.wrap([$1]));
+      }), o('Expression WhileSource', function() {
+        return $2.addBody(Block.wrap([$1]));
+      }), o('Loop', function() {
+        return $1;
+      })
+    ],
+    Loop: [
+      o('LOOP Block', function() {
+        return new While(new Literal('true')).addBody($2);
+      }), o('LOOP Expression', function() {
+        return new While(new Literal('true')).addBody(Block.wrap([$2]));
+      })
+    ],
+    For: [
+      o('Statement  ForBody', function() {
+        return new For($1, $2);
+      }), o('Expression ForBody', function() {
+        return new For($1, $2);
+      }), o('ForBody    Block', function() {
+        return new For($2, $1);
+      })
+    ],
+    ForBody: [
+      o('FOR Range', function() {
+        return {
+          source: new Value($2)
+        };
+      }), o('ForStart ForSource', function() {
+        $2.own = $1.own;
+        $2.name = $1[0];
+        $2.index = $1[1];
+        return $2;
+      })
+    ],
+    ForStart: [
+      o('FOR ForVariables', function() {
+        return $2;
+      }), o('FOR OWN ForVariables', function() {
+        $3.own = true;
+        return $3;
+      })
+    ],
+    ForValue: [
+      o('Identifier'), o('Array', function() {
+        return new Value($1);
+      }), o('Object', function() {
+        return new Value($1);
+      })
+    ],
+    ForVariables: [
+      o('ForValue', function() {
+        return [$1];
+      }), o('ForValue , ForValue', function() {
+        return [$1, $3];
+      })
+    ],
+    ForSource: [
+      o('FORIN Expression', function() {
+        return {
+          source: $2
+        };
+      }), o('FOROF Expression', function() {
+        return {
+          source: $2,
+          object: true
+        };
+      }), o('FORIN Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          guard: $4
+        };
+      }), o('FOROF Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          guard: $4,
+          object: true
+        };
+      }), o('FORIN Expression BY Expression', function() {
+        return {
+          source: $2,
+          step: $4
+        };
+      }), o('FORIN Expression WHEN Expression BY Expression', function() {
+        return {
+          source: $2,
+          guard: $4,
+          step: $6
+        };
+      }), o('FORIN Expression BY Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          step: $4,
+          guard: $6
+        };
+      })
+    ],
+    Switch: [
+      o('SWITCH Expression INDENT Whens OUTDENT', function() {
+        return new Switch($2, $4);
+      }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
+        return new Switch($2, $4, $6);
+      }), o('SWITCH INDENT Whens OUTDENT', function() {
+        return new Switch(null, $3);
+      }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
+        return new Switch(null, $3, $5);
+      })
+    ],
+    Whens: [
+      o('When'), o('Whens When', function() {
+        return $1.concat($2);
+      })
+    ],
+    When: [
+      o('LEADING_WHEN SimpleArgs Block', function() {
+        return [[$2, $3]];
+      }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
+        return [[$2, $3]];
+      })
+    ],
+    IfBlock: [
+      o('IF Expression Block', function() {
+        return new If($2, $3, {
+          type: $1
+        });
+      }), o('IfBlock ELSE IF Expression Block', function() {
+        return $1.addElse(new If($4, $5, {
+          type: $3
+        }));
+      })
+    ],
+    If: [
+      o('IfBlock'), o('IfBlock ELSE Block', function() {
+        return $1.addElse($3);
+      }), o('Statement  POST_IF Expression', function() {
+        return new If($3, Block.wrap([$1]), {
+          type: $2,
+          statement: true
+        });
+      }), o('Expression POST_IF Expression', function() {
+        return new If($3, Block.wrap([$1]), {
+          type: $2,
+          statement: true
+        });
+      })
+    ],
+    Operation: [
+      o('UNARY Expression', function() {
+        return new Op($1, $2);
+      }), o('-     Expression', (function() {
+        return new Op('-', $2);
+      }), {
+        prec: 'UNARY'
+      }), o('+     Expression', (function() {
+        return new Op('+', $2);
+      }), {
+        prec: 'UNARY'
+      }), o('-- SimpleAssignable', function() {
+        return new Op('--', $2);
+      }), o('++ SimpleAssignable', function() {
+        return new Op('++', $2);
+      }), o('SimpleAssignable --', function() {
+        return new Op('--', $1, null, true);
+      }), o('SimpleAssignable ++', function() {
+        return new Op('++', $1, null, true);
+      }), o('Expression ?', function() {
+        return new Existence($1);
+      }), o('Expression +  Expression', function() {
+        return new Op('+', $1, $3);
+      }), o('Expression -  Expression', function() {
+        return new Op('-', $1, $3);
+      }), o('Expression MATH     Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression SHIFT    Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression COMPARE  Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression LOGIC    Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression RELATION Expression', function() {
+        if ($2.charAt(0) === '!') {
+          return new Op($2.slice(1), $1, $3).invert();
+        } else {
+          return new Op($2, $1, $3);
+        }
+      }), o('SimpleAssignable COMPOUND_ASSIGN\
+       Expression', function() {
+        return new Assign($1, $3, $2);
+      }), o('SimpleAssignable COMPOUND_ASSIGN\
+       INDENT Expression OUTDENT', function() {
+        return new Assign($1, $4, $2);
+      }), o('SimpleAssignable EXTENDS Expression', function() {
+        return new Extends($1, $3);
+      })
+    ]
+  };
+  operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
+  tokens = [];
+  for (name in grammar) {
+    alternatives = grammar[name];
+    grammar[name] = (function() {
+      var _i, _j, _len, _len2, _ref, _results;
+      _results = [];
+      for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
+        alt = alternatives[_i];
+        _ref = alt[0].split(' ');
+        for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
+          token = _ref[_j];
+          if (!grammar[token]) {
+            tokens.push(token);
+          }
+        }
+        if (name === 'Root') {
+          alt[1] = "return " + alt[1];
+        }
+        _results.push(alt);
+      }
+      return _results;
+    })();
+  }
+  exports.parser = new Parser({
+    tokens: tokens.join(' '),
+    bnf: grammar,
+    operators: operators.reverse(),
+    startSymbol: 'Root'
+  });
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/helpers.js b/weinre.build/vendor/node_modules/coffee-script/lib/helpers.js
new file mode 100644
index 0000000..89be573
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/helpers.js
@@ -0,0 +1,66 @@
+(function() {
+  var extend, flatten;
+  exports.starts = function(string, literal, start) {
+    return literal === string.substr(start, literal.length);
+  };
+  exports.ends = function(string, literal, back) {
+    var len;
+    len = literal.length;
+    return literal === string.substr(string.length - len - (back || 0), len);
+  };
+  exports.compact = function(array) {
+    var item, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = array.length; _i < _len; _i++) {
+      item = array[_i];
+      if (item) {
+        _results.push(item);
+      }
+    }
+    return _results;
+  };
+  exports.count = function(string, substr) {
+    var num, pos;
+    num = pos = 0;
+    if (!substr.length) {
+      return 1 / 0;
+    }
+    while (pos = 1 + string.indexOf(substr, pos)) {
+      num++;
+    }
+    return num;
+  };
+  exports.merge = function(options, overrides) {
+    return extend(extend({}, options), overrides);
+  };
+  extend = exports.extend = function(object, properties) {
+    var key, val;
+    for (key in properties) {
+      val = properties[key];
+      object[key] = val;
+    }
+    return object;
+  };
+  exports.flatten = flatten = function(array) {
+    var element, flattened, _i, _len;
+    flattened = [];
+    for (_i = 0, _len = array.length; _i < _len; _i++) {
+      element = array[_i];
+      if (element instanceof Array) {
+        flattened = flattened.concat(flatten(element));
+      } else {
+        flattened.push(element);
+      }
+    }
+    return flattened;
+  };
+  exports.del = function(obj, key) {
+    var val;
+    val = obj[key];
+    delete obj[key];
+    return val;
+  };
+  exports.last = function(array, back) {
+    return array[array.length - (back || 0) - 1];
+  };
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/index.js b/weinre.build/vendor/node_modules/coffee-script/lib/index.js
new file mode 100644
index 0000000..38f7c1e
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/index.js
@@ -0,0 +1,8 @@
+(function() {
+  var key, val, _ref;
+  _ref = require('./coffee-script');
+  for (key in _ref) {
+    val = _ref[key];
+    exports[key] = val;
+  }
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/lexer.js b/weinre.build/vendor/node_modules/coffee-script/lib/lexer.js
new file mode 100644
index 0000000..4764bf6
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/lexer.js
@@ -0,0 +1,656 @@
+(function() {
+  var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
+  var __indexOf = Array.prototype.indexOf || function(item) {
+    for (var i = 0, l = this.length; i < l; i++) {
+      if (this[i] === item) return i;
+    }
+    return -1;
+  };
+  Rewriter = require('./rewriter').Rewriter;
+  _ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
+  exports.Lexer = Lexer = (function() {
+    function Lexer() {}
+    Lexer.prototype.tokenize = function(code, opts) {
+      var i;
+      if (opts == null) {
+        opts = {};
+      }
+      if (WHITESPACE.test(code)) {
+        code = "\n" + code;
+      }
+      code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
+      this.code = code;
+      this.line = opts.line || 0;
+      this.indent = 0;
+      this.indebt = 0;
+      this.outdebt = 0;
+      this.indents = [];
+      this.tokens = [];
+      i = 0;
+      while (this.chunk = code.slice(i)) {
+        i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
+      }
+      this.closeIndentation();
+      if (opts.rewrite === false) {
+        return this.tokens;
+      }
+      return (new Rewriter).rewrite(this.tokens);
+    };
+    Lexer.prototype.identifierToken = function() {
+      var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
+      if (!(match = IDENTIFIER.exec(this.chunk))) {
+        return 0;
+      }
+      input = match[0], id = match[1], colon = match[2];
+      if (id === 'own' && this.tag() === 'FOR') {
+        this.token('OWN', id);
+        return id.length;
+      }
+      forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
+      tag = 'IDENTIFIER';
+      if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
+        tag = id.toUpperCase();
+        if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
+          tag = 'LEADING_WHEN';
+        } else if (tag === 'FOR') {
+          this.seenFor = true;
+        } else if (tag === 'UNLESS') {
+          tag = 'IF';
+        } else if (__indexOf.call(UNARY, tag) >= 0) {
+          tag = 'UNARY';
+        } else if (__indexOf.call(RELATION, tag) >= 0) {
+          if (tag !== 'INSTANCEOF' && this.seenFor) {
+            tag = 'FOR' + tag;
+            this.seenFor = false;
+          } else {
+            tag = 'RELATION';
+            if (this.value() === '!') {
+              this.tokens.pop();
+              id = '!' + id;
+            }
+          }
+        }
+      }
+      if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
+        if (forcedIdentifier) {
+          tag = 'IDENTIFIER';
+          id = new String(id);
+          id.reserved = true;
+        } else if (__indexOf.call(RESERVED, id) >= 0) {
+          this.identifierError(id);
+        }
+      }
+      if (!forcedIdentifier) {
+        if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
+          id = COFFEE_ALIAS_MAP[id];
+        }
+        tag = (function() {
+          switch (id) {
+            case '!':
+              return 'UNARY';
+            case '==':
+            case '!=':
+              return 'COMPARE';
+            case '&&':
+            case '||':
+              return 'LOGIC';
+            case 'true':
+            case 'false':
+            case 'null':
+            case 'undefined':
+              return 'BOOL';
+            case 'break':
+            case 'continue':
+            case 'debugger':
+              return 'STATEMENT';
+            default:
+              return tag;
+          }
+        })();
+      }
+      this.token(tag, id);
+      if (colon) {
+        this.token(':', ':');
+      }
+      return input.length;
+    };
+    Lexer.prototype.numberToken = function() {
+      var match, number;
+      if (!(match = NUMBER.exec(this.chunk))) {
+        return 0;
+      }
+      number = match[0];
+      this.token('NUMBER', number);
+      return number.length;
+    };
+    Lexer.prototype.stringToken = function() {
+      var match, string;
+      switch (this.chunk.charAt(0)) {
+        case "'":
+          if (!(match = SIMPLESTR.exec(this.chunk))) {
+            return 0;
+          }
+          this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
+          break;
+        case '"':
+          if (!(string = this.balancedString(this.chunk, '"'))) {
+            return 0;
+          }
+          if (0 < string.indexOf('#{', 1)) {
+            this.interpolateString(string.slice(1, -1));
+          } else {
+            this.token('STRING', this.escapeLines(string));
+          }
+          break;
+        default:
+          return 0;
+      }
+      this.line += count(string, '\n');
+      return string.length;
+    };
+    Lexer.prototype.heredocToken = function() {
+      var doc, heredoc, match, quote;
+      if (!(match = HEREDOC.exec(this.chunk))) {
+        return 0;
+      }
+      heredoc = match[0];
+      quote = heredoc.charAt(0);
+      doc = this.sanitizeHeredoc(match[2], {
+        quote: quote,
+        indent: null
+      });
+      if (quote === '"' && 0 <= doc.indexOf('#{')) {
+        this.interpolateString(doc, {
+          heredoc: true
+        });
+      } else {
+        this.token('STRING', this.makeString(doc, quote, true));
+      }
+      this.line += count(heredoc, '\n');
+      return heredoc.length;
+    };
+    Lexer.prototype.commentToken = function() {
+      var comment, here, match;
+      if (!(match = this.chunk.match(COMMENT))) {
+        return 0;
+      }
+      comment = match[0], here = match[1];
+      if (here) {
+        this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
+          herecomment: true,
+          indent: Array(this.indent + 1).join(' ')
+        }));
+        this.token('TERMINATOR', '\n');
+      }
+      this.line += count(comment, '\n');
+      return comment.length;
+    };
+    Lexer.prototype.jsToken = function() {
+      var match, script;
+      if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
+        return 0;
+      }
+      this.token('JS', (script = match[0]).slice(1, -1));
+      return script.length;
+    };
+    Lexer.prototype.regexToken = function() {
+      var length, match, prev, regex, _ref2;
+      if (this.chunk.charAt(0) !== '/') {
+        return 0;
+      }
+      if (match = HEREGEX.exec(this.chunk)) {
+        length = this.heregexToken(match);
+        this.line += count(match[0], '\n');
+        return length;
+      }
+      prev = last(this.tokens);
+      if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
+        return 0;
+      }
+      if (!(match = REGEX.exec(this.chunk))) {
+        return 0;
+      }
+      regex = match[0];
+      this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
+      return regex.length;
+    };
+    Lexer.prototype.heregexToken = function(match) {
+      var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
+      heregex = match[0], body = match[1], flags = match[2];
+      if (0 > body.indexOf('#{')) {
+        re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
+        this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
+        return heregex.length;
+      }
+      this.token('IDENTIFIER', 'RegExp');
+      this.tokens.push(['CALL_START', '(']);
+      tokens = [];
+      _ref2 = this.interpolateString(body, {
+        regex: true
+      });
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
+        if (tag === 'TOKENS') {
+          tokens.push.apply(tokens, value);
+        } else {
+          if (!(value = value.replace(HEREGEX_OMIT, ''))) {
+            continue;
+          }
+          value = value.replace(/\\/g, '\\\\');
+          tokens.push(['STRING', this.makeString(value, '"', true)]);
+        }
+        tokens.push(['+', '+']);
+      }
+      tokens.pop();
+      if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
+        this.tokens.push(['STRING', '""'], ['+', '+']);
+      }
+      (_ref5 = this.tokens).push.apply(_ref5, tokens);
+      if (flags) {
+        this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
+      }
+      this.token(')', ')');
+      return heregex.length;
+    };
+    Lexer.prototype.lineToken = function() {
+      var diff, indent, match, noNewlines, prev, size;
+      if (!(match = MULTI_DENT.exec(this.chunk))) {
+        return 0;
+      }
+      indent = match[0];
+      this.line += count(indent, '\n');
+      prev = last(this.tokens, 1);
+      size = indent.length - 1 - indent.lastIndexOf('\n');
+      noNewlines = this.unfinished();
+      if (size - this.indebt === this.indent) {
+        if (noNewlines) {
+          this.suppressNewlines();
+        } else {
+          this.newlineToken();
+        }
+        return indent.length;
+      }
+      if (size > this.indent) {
+        if (noNewlines) {
+          this.indebt = size - this.indent;
+          this.suppressNewlines();
+          return indent.length;
+        }
+        diff = size - this.indent + this.outdebt;
+        this.token('INDENT', diff);
+        this.indents.push(diff);
+        this.outdebt = this.indebt = 0;
+      } else {
+        this.indebt = 0;
+        this.outdentToken(this.indent - size, noNewlines);
+      }
+      this.indent = size;
+      return indent.length;
+    };
+    Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
+      var dent, len;
+      while (moveOut > 0) {
+        len = this.indents.length - 1;
+        if (this.indents[len] === void 0) {
+          moveOut = 0;
+        } else if (this.indents[len] === this.outdebt) {
+          moveOut -= this.outdebt;
+          this.outdebt = 0;
+        } else if (this.indents[len] < this.outdebt) {
+          this.outdebt -= this.indents[len];
+          moveOut -= this.indents[len];
+        } else {
+          dent = this.indents.pop() - this.outdebt;
+          moveOut -= dent;
+          this.outdebt = 0;
+          this.token('OUTDENT', dent);
+        }
+      }
+      if (dent) {
+        this.outdebt -= moveOut;
+      }
+      if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
+        this.token('TERMINATOR', '\n');
+      }
+      return this;
+    };
+    Lexer.prototype.whitespaceToken = function() {
+      var match, nline, prev;
+      if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
+        return 0;
+      }
+      prev = last(this.tokens);
+      if (prev) {
+        prev[match ? 'spaced' : 'newLine'] = true;
+      }
+      if (match) {
+        return match[0].length;
+      } else {
+        return 0;
+      }
+    };
+    Lexer.prototype.newlineToken = function() {
+      if (this.tag() !== 'TERMINATOR') {
+        this.token('TERMINATOR', '\n');
+      }
+      return this;
+    };
+    Lexer.prototype.suppressNewlines = function() {
+      if (this.value() === '\\') {
+        this.tokens.pop();
+      }
+      return this;
+    };
+    Lexer.prototype.literalToken = function() {
+      var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
+      if (match = OPERATOR.exec(this.chunk)) {
+        value = match[0];
+        if (CODE.test(value)) {
+          this.tagParameters();
+        }
+      } else {
+        value = this.chunk.charAt(0);
+      }
+      tag = value;
+      prev = last(this.tokens);
+      if (value === '=' && prev) {
+        if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
+          this.assignmentError();
+        }
+        if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
+          prev[0] = 'COMPOUND_ASSIGN';
+          prev[1] += '=';
+          return value.length;
+        }
+      }
+      if (value === ';') {
+        tag = 'TERMINATOR';
+      } else if (__indexOf.call(MATH, value) >= 0) {
+        tag = 'MATH';
+      } else if (__indexOf.call(COMPARE, value) >= 0) {
+        tag = 'COMPARE';
+      } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {
+        tag = 'COMPOUND_ASSIGN';
+      } else if (__indexOf.call(UNARY, value) >= 0) {
+        tag = 'UNARY';
+      } else if (__indexOf.call(SHIFT, value) >= 0) {
+        tag = 'SHIFT';
+      } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
+        tag = 'LOGIC';
+      } else if (prev && !prev.spaced) {
+        if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
+          if (prev[0] === '?') {
+            prev[0] = 'FUNC_EXIST';
+          }
+          tag = 'CALL_START';
+        } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
+          tag = 'INDEX_START';
+          switch (prev[0]) {
+            case '?':
+              prev[0] = 'INDEX_SOAK';
+              break;
+            case '::':
+              prev[0] = 'INDEX_PROTO';
+          }
+        }
+      }
+      this.token(tag, value);
+      return value.length;
+    };
+    Lexer.prototype.sanitizeHeredoc = function(doc, options) {
+      var attempt, herecomment, indent, match, _ref2;
+      indent = options.indent, herecomment = options.herecomment;
+      if (herecomment) {
+        if (HEREDOC_ILLEGAL.test(doc)) {
+          throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
+        }
+        if (doc.indexOf('\n') <= 0) {
+          return doc;
+        }
+      } else {
+        while (match = HEREDOC_INDENT.exec(doc)) {
+          attempt = match[1];
+          if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
+            indent = attempt;
+          }
+        }
+      }
+      if (indent) {
+        doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
+      }
+      if (!herecomment) {
+        doc = doc.replace(/^\n/, '');
+      }
+      return doc;
+    };
+    Lexer.prototype.tagParameters = function() {
+      var i, stack, tok, tokens;
+      if (this.tag() !== ')') {
+        return this;
+      }
+      stack = [];
+      tokens = this.tokens;
+      i = tokens.length;
+      tokens[--i][0] = 'PARAM_END';
+      while (tok = tokens[--i]) {
+        switch (tok[0]) {
+          case ')':
+            stack.push(tok);
+            break;
+          case '(':
+          case 'CALL_START':
+            if (stack.length) {
+              stack.pop();
+            } else if (tok[0] === '(') {
+              tok[0] = 'PARAM_START';
+              return this;
+            } else {
+              return this;
+            }
+        }
+      }
+      return this;
+    };
+    Lexer.prototype.closeIndentation = function() {
+      return this.outdentToken(this.indent);
+    };
+    Lexer.prototype.identifierError = function(word) {
+      throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
+    };
+    Lexer.prototype.assignmentError = function() {
+      throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
+    };
+    Lexer.prototype.balancedString = function(str, end) {
+      var i, letter, match, prev, stack, _ref2;
+      stack = [end];
+      for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
+        switch (letter = str.charAt(i)) {
+          case '\\':
+            i++;
+            continue;
+          case end:
+            stack.pop();
+            if (!stack.length) {
+              return str.slice(0, i + 1);
+            }
+            end = stack[stack.length - 1];
+            continue;
+        }
+        if (end === '}' && (letter === '"' || letter === "'")) {
+          stack.push(end = letter);
+        } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
+          i += match[0].length - 1;
+        } else if (end === '}' && letter === '{') {
+          stack.push(end = '}');
+        } else if (end === '"' && prev === '#' && letter === '{') {
+          stack.push(end = '}');
+        }
+        prev = letter;
+      }
+      throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
+    };
+    Lexer.prototype.interpolateString = function(str, options) {
+      var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
+      if (options == null) {
+        options = {};
+      }
+      heredoc = options.heredoc, regex = options.regex;
+      tokens = [];
+      pi = 0;
+      i = -1;
+      while (letter = str.charAt(i += 1)) {
+        if (letter === '\\') {
+          i += 1;
+          continue;
+        }
+        if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
+          continue;
+        }
+        if (pi < i) {
+          tokens.push(['NEOSTRING', str.slice(pi, i)]);
+        }
+        inner = expr.slice(1, -1);
+        if (inner.length) {
+          nested = new Lexer().tokenize(inner, {
+            line: this.line,
+            rewrite: false
+          });
+          nested.pop();
+          if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
+            nested.shift();
+          }
+          if (len = nested.length) {
+            if (len > 1) {
+              nested.unshift(['(', '(']);
+              nested.push([')', ')']);
+            }
+            tokens.push(['TOKENS', nested]);
+          }
+        }
+        i += expr.length;
+        pi = i + 1;
+      }
+      if ((i > pi && pi < str.length)) {
+        tokens.push(['NEOSTRING', str.slice(pi)]);
+      }
+      if (regex) {
+        return tokens;
+      }
+      if (!tokens.length) {
+        return this.token('STRING', '""');
+      }
+      if (tokens[0][0] !== 'NEOSTRING') {
+        tokens.unshift(['', '']);
+      }
+      if (interpolated = tokens.length > 1) {
+        this.token('(', '(');
+      }
+      for (i = 0, _len = tokens.length; i < _len; i++) {
+        _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
+        if (i) {
+          this.token('+', '+');
+        }
+        if (tag === 'TOKENS') {
+          (_ref4 = this.tokens).push.apply(_ref4, value);
+        } else {
+          this.token('STRING', this.makeString(value, '"', heredoc));
+        }
+      }
+      if (interpolated) {
+        this.token(')', ')');
+      }
+      return tokens;
+    };
+    Lexer.prototype.token = function(tag, value) {
+      return this.tokens.push([tag, value, this.line]);
+    };
+    Lexer.prototype.tag = function(index, tag) {
+      var tok;
+      return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
+    };
+    Lexer.prototype.value = function(index, val) {
+      var tok;
+      return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
+    };
+    Lexer.prototype.unfinished = function() {
+      var prev, value;
+      return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
+    };
+    Lexer.prototype.escapeLines = function(str, heredoc) {
+      return str.replace(MULTILINER, heredoc ? '\\n' : '');
+    };
+    Lexer.prototype.makeString = function(body, quote, heredoc) {
+      if (!body) {
+        return quote + quote;
+      }
+      body = body.replace(/\\([\s\S])/g, function(match, contents) {
+        if (contents === '\n' || contents === quote) {
+          return contents;
+        } else {
+          return match;
+        }
+      });
+      body = body.replace(RegExp("" + quote, "g"), '\\$&');
+      return quote + this.escapeLines(body, heredoc) + quote;
+    };
+    return Lexer;
+  })();
+  JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
+  COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
+  COFFEE_ALIAS_MAP = {
+    and: '&&',
+    or: '||',
+    is: '==',
+    isnt: '!=',
+    not: '!',
+    yes: 'true',
+    no: 'false',
+    on: 'true',
+    off: 'false'
+  };
+  COFFEE_ALIASES = (function() {
+    var _results;
+    _results = [];
+    for (key in COFFEE_ALIAS_MAP) {
+      _results.push(key);
+    }
+    return _results;
+  })();
+  COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
+  RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
+  JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
+  exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
+  IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
+  NUMBER = /^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
+  HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
+  OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
+  WHITESPACE = /^[^\n\S]+/;
+  COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
+  CODE = /^[-=]>/;
+  MULTI_DENT = /^(?:\n[^\n\S]*)+/;
+  SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
+  JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
+  REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
+  HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
+  HEREGEX_OMIT = /\s+(?:#.*)?/g;
+  MULTILINER = /\n/g;
+  HEREDOC_INDENT = /\n+([^\n\S]*)/g;
+  HEREDOC_ILLEGAL = /\*\//;
+  ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
+  LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
+  TRAILING_SPACES = /\s+$/;
+  NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
+  COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
+  UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
+  LOGIC = ['&&', '||', '&', '|', '^'];
+  SHIFT = ['<<', '>>', '>>>'];
+  COMPARE = ['==', '!=', '<', '>', '<=', '>='];
+  MATH = ['*', '/', '%'];
+  RELATION = ['IN', 'OF', 'INSTANCEOF'];
+  BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
+  NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
+  NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
+  CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
+  INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
+  LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/nodes.js b/weinre.build/vendor/node_modules/coffee-script/lib/nodes.js
new file mode 100644
index 0000000..1131062
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/nodes.js
@@ -0,0 +1,2289 @@
+(function() {
+  var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref;
+  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
+    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
+    function ctor() { this.constructor = child; }
+    ctor.prototype = parent.prototype;
+    child.prototype = new ctor;
+    child.__super__ = parent.prototype;
+    return child;
+  }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = Array.prototype.indexOf || function(item) {
+    for (var i = 0, l = this.length; i < l; i++) {
+      if (this[i] === item) return i;
+    }
+    return -1;
+  };
+  Scope = require('./scope').Scope;
+  _ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
+  exports.extend = extend;
+  YES = function() {
+    return true;
+  };
+  NO = function() {
+    return false;
+  };
+  THIS = function() {
+    return this;
+  };
+  NEGATE = function() {
+    this.negated = !this.negated;
+    return this;
+  };
+  exports.Base = Base = (function() {
+    function Base() {}
+    Base.prototype.compile = function(o, lvl) {
+      var node;
+      o = extend({}, o);
+      if (lvl) {
+        o.level = lvl;
+      }
+      node = this.unfoldSoak(o) || this;
+      node.tab = o.indent;
+      if (o.level === LEVEL_TOP || !node.isStatement(o)) {
+        return node.compileNode(o);
+      } else {
+        return node.compileClosure(o);
+      }
+    };
+    Base.prototype.compileClosure = function(o) {
+      if (this.jumps() || this instanceof Throw) {
+        throw SyntaxError('cannot use a pure statement in an expression.');
+      }
+      o.sharedScope = true;
+      return Closure.wrap(this).compileNode(o);
+    };
+    Base.prototype.cache = function(o, level, reused) {
+      var ref, sub;
+      if (!this.isComplex()) {
+        ref = level ? this.compile(o, level) : this;
+        return [ref, ref];
+      } else {
+        ref = new Literal(reused || o.scope.freeVariable('ref'));
+        sub = new Assign(ref, this);
+        if (level) {
+          return [sub.compile(o, level), ref.value];
+        } else {
+          return [sub, ref];
+        }
+      }
+    };
+    Base.prototype.compileLoopReference = function(o, name) {
+      var src, tmp;
+      src = tmp = this.compile(o, LEVEL_LIST);
+      if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) {
+        src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src;
+      }
+      return [src, tmp];
+    };
+    Base.prototype.makeReturn = function() {
+      return new Return(this);
+    };
+    Base.prototype.contains = function(pred) {
+      var contains;
+      contains = false;
+      this.traverseChildren(false, function(node) {
+        if (pred(node)) {
+          contains = true;
+          return false;
+        }
+      });
+      return contains;
+    };
+    Base.prototype.containsType = function(type) {
+      return this instanceof type || this.contains(function(node) {
+        return node instanceof type;
+      });
+    };
+    Base.prototype.lastNonComment = function(list) {
+      var i;
+      i = list.length;
+      while (i--) {
+        if (!(list[i] instanceof Comment)) {
+          return list[i];
+        }
+      }
+      return null;
+    };
+    Base.prototype.toString = function(idt, name) {
+      var tree;
+      if (idt == null) {
+        idt = '';
+      }
+      if (name == null) {
+        name = this.constructor.name;
+      }
+      tree = '\n' + idt + name;
+      if (this.soak) {
+        tree += '?';
+      }
+      this.eachChild(function(node) {
+        return tree += node.toString(idt + TAB);
+      });
+      return tree;
+    };
+    Base.prototype.eachChild = function(func) {
+      var attr, child, _i, _j, _len, _len2, _ref2, _ref3;
+      if (!this.children) {
+        return this;
+      }
+      _ref2 = this.children;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        attr = _ref2[_i];
+        if (this[attr]) {
+          _ref3 = flatten([this[attr]]);
+          for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
+            child = _ref3[_j];
+            if (func(child) === false) {
+              return this;
+            }
+          }
+        }
+      }
+      return this;
+    };
+    Base.prototype.traverseChildren = function(crossScope, func) {
+      return this.eachChild(function(child) {
+        if (func(child) === false) {
+          return false;
+        }
+        return child.traverseChildren(crossScope, func);
+      });
+    };
+    Base.prototype.invert = function() {
+      return new Op('!', this);
+    };
+    Base.prototype.unwrapAll = function() {
+      var node;
+      node = this;
+      while (node !== (node = node.unwrap())) {
+        continue;
+      }
+      return node;
+    };
+    Base.prototype.children = [];
+    Base.prototype.isStatement = NO;
+    Base.prototype.jumps = NO;
+    Base.prototype.isComplex = YES;
+    Base.prototype.isChainable = NO;
+    Base.prototype.isAssignable = NO;
+    Base.prototype.unwrap = THIS;
+    Base.prototype.unfoldSoak = NO;
+    Base.prototype.assigns = NO;
+    return Base;
+  })();
+  exports.Block = Block = (function() {
+    __extends(Block, Base);
+    function Block(nodes) {
+      this.expressions = compact(flatten(nodes || []));
+    }
+    Block.prototype.children = ['expressions'];
+    Block.prototype.push = function(node) {
+      this.expressions.push(node);
+      return this;
+    };
+    Block.prototype.pop = function() {
+      return this.expressions.pop();
+    };
+    Block.prototype.unshift = function(node) {
+      this.expressions.unshift(node);
+      return this;
+    };
+    Block.prototype.unwrap = function() {
+      if (this.expressions.length === 1) {
+        return this.expressions[0];
+      } else {
+        return this;
+      }
+    };
+    Block.prototype.isEmpty = function() {
+      return !this.expressions.length;
+    };
+    Block.prototype.isStatement = function(o) {
+      var exp, _i, _len, _ref2;
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        exp = _ref2[_i];
+        if (exp.isStatement(o)) {
+          return true;
+        }
+      }
+      return false;
+    };
+    Block.prototype.jumps = function(o) {
+      var exp, _i, _len, _ref2;
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        exp = _ref2[_i];
+        if (exp.jumps(o)) {
+          return exp;
+        }
+      }
+    };
+    Block.prototype.makeReturn = function() {
+      var expr, len;
+      len = this.expressions.length;
+      while (len--) {
+        expr = this.expressions[len];
+        if (!(expr instanceof Comment)) {
+          this.expressions[len] = expr.makeReturn();
+          if (expr instanceof Return && !expr.expression) {
+            this.expressions.splice(len, 1);
+          }
+          break;
+        }
+      }
+      return this;
+    };
+    Block.prototype.compile = function(o, level) {
+      if (o == null) {
+        o = {};
+      }
+      if (o.scope) {
+        return Block.__super__.compile.call(this, o, level);
+      } else {
+        return this.compileRoot(o);
+      }
+    };
+    Block.prototype.compileNode = function(o) {
+      var code, codes, node, top, _i, _len, _ref2;
+      this.tab = o.indent;
+      top = o.level === LEVEL_TOP;
+      codes = [];
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        node = _ref2[_i];
+        node = node.unwrapAll();
+        node = node.unfoldSoak(o) || node;
+        if (node instanceof Block) {
+          codes.push(node.compileNode(o));
+        } else if (top) {
+          node.front = true;
+          code = node.compile(o);
+          codes.push(node.isStatement(o) ? code : this.tab + code + ';');
+        } else {
+          codes.push(node.compile(o, LEVEL_LIST));
+        }
+      }
+      if (top) {
+        return codes.join('\n');
+      }
+      code = codes.join(', ') || 'void 0';
+      if (codes.length > 1 && o.level >= LEVEL_LIST) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+    Block.prototype.compileRoot = function(o) {
+      var code;
+      o.indent = this.tab = o.bare ? '' : TAB;
+      o.scope = new Scope(null, this, null);
+      o.level = LEVEL_TOP;
+      code = this.compileWithDeclarations(o);
+      if (o.bare) {
+        return code;
+      } else {
+        return "(function() {\n" + code + "\n}).call(this);\n";
+      }
+    };
+    Block.prototype.compileWithDeclarations = function(o) {
+      var assigns, code, declars, exp, i, post, rest, scope, _len, _ref2;
+      code = post = '';
+      _ref2 = this.expressions;
+      for (i = 0, _len = _ref2.length; i < _len; i++) {
+        exp = _ref2[i];
+        exp = exp.unwrap();
+        if (!(exp instanceof Comment || exp instanceof Literal)) {
+          break;
+        }
+      }
+      o = merge(o, {
+        level: LEVEL_TOP
+      });
+      if (i) {
+        rest = this.expressions.splice(i, this.expressions.length);
+        code = this.compileNode(o);
+        this.expressions = rest;
+      }
+      post = this.compileNode(o);
+      scope = o.scope;
+      if (scope.expressions === this) {
+        declars = o.scope.hasDeclarations();
+        assigns = scope.hasAssignments;
+        if ((declars || assigns) && i) {
+          code += '\n';
+        }
+        if (declars) {
+          code += "" + this.tab + "var " + (scope.declaredVariables().join(', ')) + ";\n";
+        }
+        if (assigns) {
+          code += "" + this.tab + "var " + (multident(scope.assignedVariables().join(', '), this.tab)) + ";\n";
+        }
+      }
+      return code + post;
+    };
+    Block.wrap = function(nodes) {
+      if (nodes.length === 1 && nodes[0] instanceof Block) {
+        return nodes[0];
+      }
+      return new Block(nodes);
+    };
+    return Block;
+  })();
+  exports.Literal = Literal = (function() {
+    __extends(Literal, Base);
+    function Literal(value) {
+      this.value = value;
+    }
+    Literal.prototype.makeReturn = function() {
+      if (this.isStatement()) {
+        return this;
+      } else {
+        return new Return(this);
+      }
+    };
+    Literal.prototype.isAssignable = function() {
+      return IDENTIFIER.test(this.value);
+    };
+    Literal.prototype.isStatement = function() {
+      var _ref2;
+      return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';
+    };
+    Literal.prototype.isComplex = NO;
+    Literal.prototype.assigns = function(name) {
+      return name === this.value;
+    };
+    Literal.prototype.jumps = function(o) {
+      if (!this.isStatement()) {
+        return false;
+      }
+      if (!(o && (o.loop || o.block && (this.value !== 'continue')))) {
+        return this;
+      } else {
+        return false;
+      }
+    };
+    Literal.prototype.compileNode = function(o) {
+      var code;
+      code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value.reserved ? "\"" + this.value + "\"" : this.value;
+      if (this.isStatement()) {
+        return "" + this.tab + code + ";";
+      } else {
+        return code;
+      }
+    };
+    Literal.prototype.toString = function() {
+      return ' "' + this.value + '"';
+    };
+    return Literal;
+  })();
+  exports.Return = Return = (function() {
+    __extends(Return, Base);
+    function Return(expr) {
+      if (expr && !expr.unwrap().isUndefined) {
+        this.expression = expr;
+      }
+    }
+    Return.prototype.children = ['expression'];
+    Return.prototype.isStatement = YES;
+    Return.prototype.makeReturn = THIS;
+    Return.prototype.jumps = THIS;
+    Return.prototype.compile = function(o, level) {
+      var expr, _ref2;
+      expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0;
+      if (expr && !(expr instanceof Return)) {
+        return expr.compile(o, level);
+      } else {
+        return Return.__super__.compile.call(this, o, level);
+      }
+    };
+    Return.prototype.compileNode = function(o) {
+      return this.tab + ("return" + (this.expression ? ' ' + this.expression.compile(o, LEVEL_PAREN) : '') + ";");
+    };
+    return Return;
+  })();
+  exports.Value = Value = (function() {
+    __extends(Value, Base);
+    function Value(base, props, tag) {
+      if (!props && base instanceof Value) {
+        return base;
+      }
+      this.base = base;
+      this.properties = props || [];
+      if (tag) {
+        this[tag] = true;
+      }
+      return this;
+    }
+    Value.prototype.children = ['base', 'properties'];
+    Value.prototype.push = function(prop) {
+      this.properties.push(prop);
+      return this;
+    };
+    Value.prototype.hasProperties = function() {
+      return !!this.properties.length;
+    };
+    Value.prototype.isArray = function() {
+      return !this.properties.length && this.base instanceof Arr;
+    };
+    Value.prototype.isComplex = function() {
+      return this.hasProperties() || this.base.isComplex();
+    };
+    Value.prototype.isAssignable = function() {
+      return this.hasProperties() || this.base.isAssignable();
+    };
+    Value.prototype.isSimpleNumber = function() {
+      return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
+    };
+    Value.prototype.isAtomic = function() {
+      var node, _i, _len, _ref2;
+      _ref2 = this.properties.concat(this.base);
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        node = _ref2[_i];
+        if (node.soak || node instanceof Call) {
+          return false;
+        }
+      }
+      return true;
+    };
+    Value.prototype.isStatement = function(o) {
+      return !this.properties.length && this.base.isStatement(o);
+    };
+    Value.prototype.assigns = function(name) {
+      return !this.properties.length && this.base.assigns(name);
+    };
+    Value.prototype.jumps = function(o) {
+      return !this.properties.length && this.base.jumps(o);
+    };
+    Value.prototype.isObject = function(onlyGenerated) {
+      if (this.properties.length) {
+        return false;
+      }
+      return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated);
+    };
+    Value.prototype.isSplice = function() {
+      return last(this.properties) instanceof Slice;
+    };
+    Value.prototype.makeReturn = function() {
+      if (this.properties.length) {
+        return Value.__super__.makeReturn.call(this);
+      } else {
+        return this.base.makeReturn();
+      }
+    };
+    Value.prototype.unwrap = function() {
+      if (this.properties.length) {
+        return this;
+      } else {
+        return this.base;
+      }
+    };
+    Value.prototype.cacheReference = function(o) {
+      var base, bref, name, nref;
+      name = last(this.properties);
+      if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) {
+        return [this, this];
+      }
+      base = new Value(this.base, this.properties.slice(0, -1));
+      if (base.isComplex()) {
+        bref = new Literal(o.scope.freeVariable('base'));
+        base = new Value(new Parens(new Assign(bref, base)));
+      }
+      if (!name) {
+        return [base, bref];
+      }
+      if (name.isComplex()) {
+        nref = new Literal(o.scope.freeVariable('name'));
+        name = new Index(new Assign(nref, name.index));
+        nref = new Index(nref);
+      }
+      return [base.push(name), new Value(bref || base.base, [nref || name])];
+    };
+    Value.prototype.compileNode = function(o) {
+      var code, prop, props, _i, _len;
+      this.base.front = this.front;
+      props = this.properties;
+      code = this.base.compile(o, props.length ? LEVEL_ACCESS : null);
+      if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) {
+        code = "" + code + ".";
+      }
+      for (_i = 0, _len = props.length; _i < _len; _i++) {
+        prop = props[_i];
+        code += prop.compile(o);
+      }
+      return code;
+    };
+    Value.prototype.unfoldSoak = function(o) {
+      var result;
+      if (this.unfoldedSoak != null) {
+        return this.unfoldedSoak;
+      }
+      result = __bind(function() {
+        var fst, i, ifn, prop, ref, snd, _len, _ref2;
+        if (ifn = this.base.unfoldSoak(o)) {
+          Array.prototype.push.apply(ifn.body.properties, this.properties);
+          return ifn;
+        }
+        _ref2 = this.properties;
+        for (i = 0, _len = _ref2.length; i < _len; i++) {
+          prop = _ref2[i];
+          if (prop.soak) {
+            prop.soak = false;
+            fst = new Value(this.base, this.properties.slice(0, i));
+            snd = new Value(this.base, this.properties.slice(i));
+            if (fst.isComplex()) {
+              ref = new Literal(o.scope.freeVariable('ref'));
+              fst = new Parens(new Assign(ref, fst));
+              snd.base = ref;
+            }
+            return new If(new Existence(fst), snd, {
+              soak: true
+            });
+          }
+        }
+        return null;
+      }, this)();
+      return this.unfoldedSoak = result || false;
+    };
+    return Value;
+  })();
+  exports.Comment = Comment = (function() {
+    __extends(Comment, Base);
+    function Comment(comment) {
+      this.comment = comment;
+    }
+    Comment.prototype.isStatement = YES;
+    Comment.prototype.makeReturn = THIS;
+    Comment.prototype.compileNode = function(o, level) {
+      var code;
+      code = '/*' + multident(this.comment, this.tab) + '*/';
+      if ((level || o.level) === LEVEL_TOP) {
+        code = o.indent + code;
+      }
+      return code;
+    };
+    return Comment;
+  })();
+  exports.Call = Call = (function() {
+    __extends(Call, Base);
+    function Call(variable, args, soak) {
+      this.args = args != null ? args : [];
+      this.soak = soak;
+      this.isNew = false;
+      this.isSuper = variable === 'super';
+      this.variable = this.isSuper ? null : variable;
+    }
+    Call.prototype.children = ['variable', 'args'];
+    Call.prototype.newInstance = function() {
+      var base;
+      base = this.variable.base || this.variable;
+      if (base instanceof Call && !base.isNew) {
+        base.newInstance();
+      } else {
+        this.isNew = true;
+      }
+      return this;
+    };
+    Call.prototype.superReference = function(o) {
+      var method, name;
+      method = o.scope.method;
+      if (!method) {
+        throw SyntaxError('cannot call super outside of a function.');
+      }
+      name = method.name;
+      if (name == null) {
+        throw SyntaxError('cannot call super on an anonymous function.');
+      }
+      if (method.klass) {
+        return (new Value(new Literal(method.klass), [new Access(new Literal("__super__")), new Access(new Literal(name))])).compile(o);
+      } else {
+        return "" + name + ".__super__.constructor";
+      }
+    };
+    Call.prototype.unfoldSoak = function(o) {
+      var call, ifn, left, list, rite, _i, _len, _ref2, _ref3;
+      if (this.soak) {
+        if (this.variable) {
+          if (ifn = unfoldSoak(o, this, 'variable')) {
+            return ifn;
+          }
+          _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1];
+        } else {
+          left = new Literal(this.superReference(o));
+          rite = new Value(left);
+        }
+        rite = new Call(rite, this.args);
+        rite.isNew = this.isNew;
+        left = new Literal("typeof " + (left.compile(o)) + " === \"function\"");
+        return new If(left, new Value(rite), {
+          soak: true
+        });
+      }
+      call = this;
+      list = [];
+      while (true) {
+        if (call.variable instanceof Call) {
+          list.push(call);
+          call = call.variable;
+          continue;
+        }
+        if (!(call.variable instanceof Value)) {
+          break;
+        }
+        list.push(call);
+        if (!((call = call.variable.base) instanceof Call)) {
+          break;
+        }
+      }
+      _ref3 = list.reverse();
+      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+        call = _ref3[_i];
+        if (ifn) {
+          if (call.variable instanceof Call) {
+            call.variable = ifn;
+          } else {
+            call.variable.base = ifn;
+          }
+        }
+        ifn = unfoldSoak(o, call, 'variable');
+      }
+      return ifn;
+    };
+    Call.prototype.filterImplicitObjects = function(list) {
+      var node, nodes, obj, prop, properties, _i, _j, _len, _len2, _ref2;
+      nodes = [];
+      for (_i = 0, _len = list.length; _i < _len; _i++) {
+        node = list[_i];
+        if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) {
+          nodes.push(node);
+          continue;
+        }
+        obj = null;
+        _ref2 = node.base.properties;
+        for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
+          prop = _ref2[_j];
+          if (prop instanceof Assign || prop instanceof Comment) {
+            if (!obj) {
+              nodes.push(obj = new Obj(properties = [], true));
+            }
+            properties.push(prop);
+          } else {
+            nodes.push(prop);
+            obj = null;
+          }
+        }
+      }
+      return nodes;
+    };
+    Call.prototype.compileNode = function(o) {
+      var arg, args, code, _ref2;
+      if ((_ref2 = this.variable) != null) {
+        _ref2.front = this.front;
+      }
+      if (code = Splat.compileSplattedArray(o, this.args, true)) {
+        return this.compileSplat(o, code);
+      }
+      args = this.filterImplicitObjects(this.args);
+      args = ((function() {
+        var _i, _len, _results;
+        _results = [];
+        for (_i = 0, _len = args.length; _i < _len; _i++) {
+          arg = args[_i];
+          _results.push(arg.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })()).join(', ');
+      if (this.isSuper) {
+        return this.superReference(o) + (".call(this" + (args && ', ' + args) + ")");
+      } else {
+        return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")");
+      }
+    };
+    Call.prototype.compileSuper = function(args, o) {
+      return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")";
+    };
+    Call.prototype.compileSplat = function(o, splatArgs) {
+      var base, fun, idt, name, ref;
+      if (this.isSuper) {
+        return "" + (this.superReference(o)) + ".apply(this, " + splatArgs + ")";
+      }
+      if (this.isNew) {
+        idt = this.tab + TAB;
+        return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function() {})";
+      }
+      base = new Value(this.variable);
+      if ((name = base.properties.pop()) && base.isComplex()) {
+        ref = o.scope.freeVariable('ref');
+        fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
+      } else {
+        fun = base.compile(o, LEVEL_ACCESS);
+        if (SIMPLENUM.test(fun)) {
+          fun = "(" + fun + ")";
+        }
+        if (name) {
+          ref = fun;
+          fun += name.compile(o);
+        } else {
+          ref = 'null';
+        }
+      }
+      return "" + fun + ".apply(" + ref + ", " + splatArgs + ")";
+    };
+    return Call;
+  })();
+  exports.Extends = Extends = (function() {
+    __extends(Extends, Base);
+    function Extends(child, parent) {
+      this.child = child;
+      this.parent = parent;
+    }
+    Extends.prototype.children = ['child', 'parent'];
+    Extends.prototype.compile = function(o) {
+      utility('hasProp');
+      return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
+    };
+    return Extends;
+  })();
+  exports.Access = Access = (function() {
+    __extends(Access, Base);
+    function Access(name, tag) {
+      this.name = name;
+      this.name.asKey = true;
+      this.proto = tag === 'proto' ? '.prototype' : '';
+      this.soak = tag === 'soak';
+    }
+    Access.prototype.children = ['name'];
+    Access.prototype.compile = function(o) {
+      var name;
+      name = this.name.compile(o);
+      return this.proto + (IDENTIFIER.test(name) ? "." + name : "[" + name + "]");
+    };
+    Access.prototype.isComplex = NO;
+    return Access;
+  })();
+  exports.Index = Index = (function() {
+    __extends(Index, Base);
+    function Index(index) {
+      this.index = index;
+    }
+    Index.prototype.children = ['index'];
+    Index.prototype.compile = function(o) {
+      return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL_PAREN)) + "]");
+    };
+    Index.prototype.isComplex = function() {
+      return this.index.isComplex();
+    };
+    return Index;
+  })();
+  exports.Range = Range = (function() {
+    __extends(Range, Base);
+    Range.prototype.children = ['from', 'to'];
+    function Range(from, to, tag) {
+      this.from = from;
+      this.to = to;
+      this.exclusive = tag === 'exclusive';
+      this.equals = this.exclusive ? '' : '=';
+    }
+    Range.prototype.compileVariables = function(o) {
+      var step, _ref2, _ref3, _ref4, _ref5;
+      o = merge(o, {
+        top: true
+      });
+      _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1];
+      _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1];
+      if (step = del(o, 'step')) {
+        _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1];
+      }
+      _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1];
+      if (this.stepVar) {
+        return this.stepNum = this.stepVar.match(SIMPLENUM);
+      }
+    };
+    Range.prototype.compileNode = function(o) {
+      var cond, condPart, from, gt, idx, known, lt, stepPart, to, varPart, _ref2, _ref3;
+      if (!this.fromVar) {
+        this.compileVariables(o);
+      }
+      if (!o.index) {
+        return this.compileArray(o);
+      }
+      known = this.fromNum && this.toNum;
+      idx = del(o, 'index');
+      varPart = "" + idx + " = " + this.fromC;
+      if (this.toC !== this.toVar) {
+        varPart += ", " + this.toC;
+      }
+      if (this.step !== this.stepVar) {
+        varPart += ", " + this.step;
+      }
+      _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1];
+      condPart = this.stepNum ? condPart = +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), condPart = from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, condPart = "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar);
+      stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? from <= to ? "" + idx + "++" : "" + idx + "--" : "" + cond + " ? " + idx + "++ : " + idx + "--";
+      return "" + varPart + "; " + condPart + "; " + stepPart;
+    };
+    Range.prototype.compileArray = function(o) {
+      var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results;
+      if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) {
+        range = (function() {
+          _results = [];
+          for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); }
+          return _results;
+        }).apply(this);
+        if (this.exclusive) {
+          range.pop();
+        }
+        return "[" + (range.join(', ')) + "]";
+      }
+      idt = this.tab + TAB;
+      i = o.scope.freeVariable('i');
+      result = o.scope.freeVariable('results');
+      pre = "\n" + idt + result + " = [];";
+      if (this.fromNum && this.toNum) {
+        o.index = i;
+        body = this.compileNode(o);
+      } else {
+        vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : '');
+        cond = "" + this.fromVar + " <= " + this.toVar;
+        body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--";
+      }
+      post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent;
+      hasArgs = function(node) {
+        return node != null ? node.contains(function(n) {
+          return n instanceof Literal && n.value === 'arguments' && !n.asKey;
+        }) : void 0;
+      };
+      if (hasArgs(this.from) || hasArgs(this.to)) {
+        args = ', arguments';
+      }
+      return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")";
+    };
+    return Range;
+  })();
+  exports.Slice = Slice = (function() {
+    __extends(Slice, Base);
+    Slice.prototype.children = ['range'];
+    function Slice(range) {
+      this.range = range;
+      Slice.__super__.constructor.call(this);
+    }
+    Slice.prototype.compileNode = function(o) {
+      var compiled, from, fromStr, to, toStr, _ref2;
+      _ref2 = this.range, to = _ref2.to, from = _ref2.from;
+      fromStr = from && from.compile(o, LEVEL_PAREN) || '0';
+      compiled = to && to.compile(o, LEVEL_PAREN);
+      if (to && !(!this.range.exclusive && +compiled === -1)) {
+        toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? (+compiled + 1).toString() : "(" + compiled + " + 1) || 9e9");
+      }
+      return ".slice(" + fromStr + (toStr || '') + ")";
+    };
+    return Slice;
+  })();
+  exports.Obj = Obj = (function() {
+    __extends(Obj, Base);
+    function Obj(props, generated) {
+      this.generated = generated != null ? generated : false;
+      this.objects = this.properties = props || [];
+    }
+    Obj.prototype.children = ['properties'];
+    Obj.prototype.compileNode = function(o) {
+      var i, idt, indent, join, lastNoncom, node, obj, prop, props, _i, _len;
+      props = this.properties;
+      if (!props.length) {
+        if (this.front) {
+          return '({})';
+        } else {
+          return '{}';
+        }
+      }
+      if (this.generated) {
+        for (_i = 0, _len = props.length; _i < _len; _i++) {
+          node = props[_i];
+          if (node instanceof Value) {
+            throw new Error('cannot have an implicit value in an implicit object');
+          }
+        }
+      }
+      idt = o.indent += TAB;
+      lastNoncom = this.lastNonComment(this.properties);
+      props = (function() {
+        var _len2, _results;
+        _results = [];
+        for (i = 0, _len2 = props.length; i < _len2; i++) {
+          prop = props[i];
+          join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
+          indent = prop instanceof Comment ? '' : idt;
+          if (prop instanceof Value && prop["this"]) {
+            prop = new Assign(prop.properties[0].name, prop, 'object');
+          }
+          if (!(prop instanceof Comment)) {
+            if (!(prop instanceof Assign)) {
+              prop = new Assign(prop, prop, 'object');
+            }
+            (prop.variable.base || prop.variable).asKey = true;
+          }
+          _results.push(indent + prop.compile(o, LEVEL_TOP) + join);
+        }
+        return _results;
+      })();
+      props = props.join('');
+      obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}";
+      if (this.front) {
+        return "(" + obj + ")";
+      } else {
+        return obj;
+      }
+    };
+    Obj.prototype.assigns = function(name) {
+      var prop, _i, _len, _ref2;
+      _ref2 = this.properties;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        prop = _ref2[_i];
+        if (prop.assigns(name)) {
+          return true;
+        }
+      }
+      return false;
+    };
+    return Obj;
+  })();
+  exports.Arr = Arr = (function() {
+    __extends(Arr, Base);
+    function Arr(objs) {
+      this.objects = objs || [];
+    }
+    Arr.prototype.children = ['objects'];
+    Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects;
+    Arr.prototype.compileNode = function(o) {
+      var code, obj, objs;
+      if (!this.objects.length) {
+        return '[]';
+      }
+      o.indent += TAB;
+      objs = this.filterImplicitObjects(this.objects);
+      if (code = Splat.compileSplattedArray(o, objs)) {
+        return code;
+      }
+      code = ((function() {
+        var _i, _len, _results;
+        _results = [];
+        for (_i = 0, _len = objs.length; _i < _len; _i++) {
+          obj = objs[_i];
+          _results.push(obj.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })()).join(', ');
+      if (code.indexOf('\n') >= 0) {
+        return "[\n" + o.indent + code + "\n" + this.tab + "]";
+      } else {
+        return "[" + code + "]";
+      }
+    };
+    Arr.prototype.assigns = function(name) {
+      var obj, _i, _len, _ref2;
+      _ref2 = this.objects;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        obj = _ref2[_i];
+        if (obj.assigns(name)) {
+          return true;
+        }
+      }
+      return false;
+    };
+    return Arr;
+  })();
+  exports.Class = Class = (function() {
+    __extends(Class, Base);
+    function Class(variable, parent, body) {
+      this.variable = variable;
+      this.parent = parent;
+      this.body = body != null ? body : new Block;
+      this.boundFuncs = [];
+      this.body.classBody = true;
+    }
+    Class.prototype.children = ['variable', 'parent', 'body'];
+    Class.prototype.determineName = function() {
+      var decl, tail;
+      if (!this.variable) {
+        return null;
+      }
+      decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value;
+      return decl && (decl = IDENTIFIER.test(decl) && decl);
+    };
+    Class.prototype.setContext = function(name) {
+      return this.body.traverseChildren(false, function(node) {
+        if (node.classBody) {
+          return false;
+        }
+        if (node instanceof Literal && node.value === 'this') {
+          return node.value = name;
+        } else if (node instanceof Code) {
+          node.klass = name;
+          if (node.bound) {
+            return node.context = name;
+          }
+        }
+      });
+    };
+    Class.prototype.addBoundFunctions = function(o) {
+      var bvar, lhs, _i, _len, _ref2, _results;
+      if (this.boundFuncs.length) {
+        _ref2 = this.boundFuncs;
+        _results = [];
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          bvar = _ref2[_i];
+          lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
+          _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)")));
+        }
+        return _results;
+      }
+    };
+    Class.prototype.addProperties = function(node, name, o) {
+      var assign, base, exprs, func, props;
+      props = node.base.properties.slice(0);
+      exprs = (function() {
+        var _results;
+        _results = [];
+        while (assign = props.shift()) {
+          if (assign instanceof Assign) {
+            base = assign.variable.base;
+            delete assign.context;
+            func = assign.value;
+            if (base.value === 'constructor') {
+              if (this.ctor) {
+                throw new Error('cannot define more than one constructor in a class');
+              }
+              if (func.bound) {
+                throw new Error('cannot define a constructor as a bound function');
+              }
+              if (func instanceof Code) {
+                assign = this.ctor = func;
+              } else {
+                this.externalCtor = o.scope.freeVariable('class');
+                assign = new Assign(new Literal(this.externalCtor), func);
+              }
+            } else {
+              if (!assign.variable["this"]) {
+                assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]);
+              }
+              if (func instanceof Code && func.bound) {
+                this.boundFuncs.push(base);
+                func.bound = false;
+              }
+            }
+          }
+          _results.push(assign);
+        }
+        return _results;
+      }).call(this);
+      return compact(exprs);
+    };
+    Class.prototype.walkBody = function(name, o) {
+      return this.traverseChildren(false, __bind(function(child) {
+        var exps, i, node, _len, _ref2;
+        if (child instanceof Class) {
+          return false;
+        }
+        if (child instanceof Block) {
+          _ref2 = exps = child.expressions;
+          for (i = 0, _len = _ref2.length; i < _len; i++) {
+            node = _ref2[i];
+            if (node instanceof Value && node.isObject(true)) {
+              exps[i] = this.addProperties(node, name, o);
+            }
+          }
+          return child.expressions = exps = flatten(exps);
+        }
+      }, this));
+    };
+    Class.prototype.ensureConstructor = function(name) {
+      if (!this.ctor) {
+        this.ctor = new Code;
+        if (this.parent) {
+          this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)"));
+        }
+        if (this.externalCtor) {
+          this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)"));
+        }
+        this.body.expressions.unshift(this.ctor);
+      }
+      this.ctor.ctor = this.ctor.name = name;
+      this.ctor.klass = null;
+      return this.ctor.noReturn = true;
+    };
+    Class.prototype.compileNode = function(o) {
+      var decl, klass, lname, name;
+      decl = this.determineName();
+      name = decl || this.name || '_Class';
+      lname = new Literal(name);
+      this.setContext(name);
+      this.walkBody(name, o);
+      this.ensureConstructor(name);
+      if (this.parent) {
+        this.body.expressions.unshift(new Extends(lname, this.parent));
+      }
+      if (!(this.ctor instanceof Code)) {
+        this.body.expressions.unshift(this.ctor);
+      }
+      this.body.expressions.push(lname);
+      this.addBoundFunctions(o);
+      klass = new Parens(Closure.wrap(this.body), true);
+      if (this.variable) {
+        klass = new Assign(this.variable, klass);
+      }
+      return klass.compile(o);
+    };
+    return Class;
+  })();
+  exports.Assign = Assign = (function() {
+    __extends(Assign, Base);
+    function Assign(variable, value, context, options) {
+      this.variable = variable;
+      this.value = value;
+      this.context = context;
+      this.param = options && options.param;
+    }
+    Assign.prototype.children = ['variable', 'value'];
+    Assign.prototype.isStatement = function(o) {
+      return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0;
+    };
+    Assign.prototype.assigns = function(name) {
+      return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
+    };
+    Assign.prototype.unfoldSoak = function(o) {
+      return unfoldSoak(o, this, 'variable');
+    };
+    Assign.prototype.compileNode = function(o) {
+      var isValue, match, name, val, _ref2, _ref3, _ref4, _ref5;
+      if (isValue = this.variable instanceof Value) {
+        if (this.variable.isArray() || this.variable.isObject()) {
+          return this.compilePatternMatch(o);
+        }
+        if (this.variable.isSplice()) {
+          return this.compileSplice(o);
+        }
+        if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') {
+          return this.compileConditional(o);
+        }
+      }
+      name = this.variable.compile(o, LEVEL_LIST);
+      if (!(this.context || this.variable.isAssignable())) {
+        throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned.");
+      }
+      if (!(this.context || isValue && (this.variable.namespaced || this.variable.hasProperties()))) {
+        if (this.param) {
+          o.scope.add(name, 'var');
+        } else {
+          o.scope.find(name);
+        }
+      }
+      if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) {
+        if (match[1]) {
+          this.value.klass = match[1];
+        }
+        this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5];
+      }
+      val = this.value.compile(o, LEVEL_LIST);
+      if (this.context === 'object') {
+        return "" + name + ": " + val;
+      }
+      val = name + (" " + (this.context || '=') + " ") + val;
+      if (o.level <= LEVEL_LIST) {
+        return val;
+      } else {
+        return "(" + val + ")";
+      }
+    };
+    Assign.prototype.compilePatternMatch = function(o) {
+      var acc, assigns, code, i, idx, isObject, ivar, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _len, _ref2, _ref3, _ref4, _ref5;
+      top = o.level === LEVEL_TOP;
+      value = this.value;
+      objects = this.variable.base.objects;
+      if (!(olen = objects.length)) {
+        code = value.compile(o);
+        if (o.level >= LEVEL_OP) {
+          return "(" + code + ")";
+        } else {
+          return code;
+        }
+      }
+      isObject = this.variable.isObject();
+      if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {
+        if (obj instanceof Assign) {
+          _ref2 = obj, idx = _ref2.variable.base, obj = _ref2.value;
+        } else {
+          if (obj.base instanceof Parens) {
+            _ref3 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref3[0], idx = _ref3[1];
+          } else {
+            idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0);
+          }
+        }
+        acc = IDENTIFIER.test(idx.unwrap().value || 0);
+        value = new Value(value);
+        value.properties.push(new (acc ? Access : Index)(idx));
+        return new Assign(obj, value, null, {
+          param: this.param
+        }).compile(o, LEVEL_TOP);
+      }
+      vvar = value.compile(o, LEVEL_LIST);
+      assigns = [];
+      splat = false;
+      if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) {
+        assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar);
+        vvar = ref;
+      }
+      for (i = 0, _len = objects.length; i < _len; i++) {
+        obj = objects[i];
+        idx = i;
+        if (isObject) {
+          if (obj instanceof Assign) {
+            _ref4 = obj, idx = _ref4.variable.base, obj = _ref4.value;
+          } else {
+            if (obj.base instanceof Parens) {
+              _ref5 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref5[0], idx = _ref5[1];
+            } else {
+              idx = obj["this"] ? obj.properties[0].name : obj;
+            }
+          }
+        }
+        if (!splat && obj instanceof Splat) {
+          val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i;
+          if (rest = olen - i - 1) {
+            ivar = o.scope.freeVariable('i');
+            val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])";
+          } else {
+            val += ") : []";
+          }
+          val = new Literal(val);
+          splat = "" + ivar + "++";
+        } else {
+          if (obj instanceof Splat) {
+            obj = obj.name.compile(o);
+            throw SyntaxError("multiple splats are disallowed in an assignment: " + obj + " ...");
+          }
+          if (typeof idx === 'number') {
+            idx = new Literal(splat || idx);
+            acc = false;
+          } else {
+            acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);
+          }
+          val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
+        }
+        assigns.push(new Assign(obj, val, null, {
+          param: this.param
+        }).compile(o, LEVEL_TOP));
+      }
+      if (!top) {
+        assigns.push(vvar);
+      }
+      code = assigns.join(', ');
+      if (o.level < LEVEL_LIST) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+    Assign.prototype.compileConditional = function(o) {
+      var left, rite, _ref2;
+      _ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1];
+      if (__indexOf.call(this.context, "?") >= 0) {
+        o.isExistentialEquals = true;
+      }
+      return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o);
+    };
+    Assign.prototype.compileSplice = function(o) {
+      var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4;
+      _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive;
+      name = this.variable.compile(o);
+      _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1];
+      if (to) {
+        if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {
+          to = +to.compile(o) - +fromRef;
+          if (!exclusive) {
+            to += 1;
+          }
+        } else {
+          to = to.compile(o) + ' - ' + fromRef;
+          if (!exclusive) {
+            to += ' + 1';
+          }
+        }
+      } else {
+        to = "9e9";
+      }
+      _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1];
+      code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef;
+      if (o.level > LEVEL_TOP) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+    return Assign;
+  })();
+  exports.Code = Code = (function() {
+    __extends(Code, Base);
+    function Code(params, body, tag) {
+      this.params = params || [];
+      this.body = body || new Block;
+      this.bound = tag === 'boundfunc';
+      if (this.bound) {
+        this.context = 'this';
+      }
+    }
+    Code.prototype.children = ['params', 'body'];
+    Code.prototype.isStatement = function() {
+      return !!this.ctor;
+    };
+    Code.prototype.jumps = NO;
+    Code.prototype.compileNode = function(o) {
+      var code, exprs, i, idt, lit, p, param, ref, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref2, _ref3, _ref4, _ref5;
+      o.scope = new Scope(o.scope, this.body, this);
+      o.scope.shared = del(o, 'sharedScope');
+      o.indent += TAB;
+      delete o.bare;
+      vars = [];
+      exprs = [];
+      _ref2 = this.params;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        param = _ref2[_i];
+        if (param.splat) {
+          _ref3 = this.params;
+          for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
+            p = _ref3[_j];
+            if (p.name.value) {
+              o.scope.add(p.name.value, 'var', true);
+            }
+          }
+          splats = new Assign(new Value(new Arr((function() {
+            var _k, _len3, _ref4, _results;
+            _ref4 = this.params;
+            _results = [];
+            for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
+              p = _ref4[_k];
+              _results.push(p.asReference(o));
+            }
+            return _results;
+          }).call(this))), new Value(new Literal('arguments')));
+          break;
+        }
+      }
+      _ref4 = this.params;
+      for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
+        param = _ref4[_k];
+        if (param.isComplex()) {
+          val = ref = param.asReference(o);
+          if (param.value) {
+            val = new Op('?', ref, param.value);
+          }
+          exprs.push(new Assign(new Value(param.name), val, '=', {
+            param: true
+          }));
+        } else {
+          ref = param;
+          if (param.value) {
+            lit = new Literal(ref.name.value + ' == null');
+            val = new Assign(new Value(param.name), param.value, '=');
+            exprs.push(new If(lit, val));
+          }
+        }
+        if (!splats) {
+          vars.push(ref);
+        }
+      }
+      wasEmpty = this.body.isEmpty();
+      if (splats) {
+        exprs.unshift(splats);
+      }
+      if (exprs.length) {
+        (_ref5 = this.body.expressions).unshift.apply(_ref5, exprs);
+      }
+      if (!splats) {
+        for (i = 0, _len4 = vars.length; i < _len4; i++) {
+          v = vars[i];
+          o.scope.parameter(vars[i] = v.compile(o));
+        }
+      }
+      if (!(wasEmpty || this.noReturn)) {
+        this.body.makeReturn();
+      }
+      idt = o.indent;
+      code = 'function';
+      if (this.ctor) {
+        code += ' ' + this.name;
+      }
+      code += '(' + vars.join(', ') + ') {';
+      if (!this.body.isEmpty()) {
+        code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab;
+      }
+      code += '}';
+      if (this.ctor) {
+        return this.tab + code;
+      }
+      if (this.bound) {
+        return utility('bind') + ("(" + code + ", " + this.context + ")");
+      }
+      if (this.front || (o.level >= LEVEL_ACCESS)) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+    Code.prototype.traverseChildren = function(crossScope, func) {
+      if (crossScope) {
+        return Code.__super__.traverseChildren.call(this, crossScope, func);
+      }
+    };
+    return Code;
+  })();
+  exports.Param = Param = (function() {
+    __extends(Param, Base);
+    function Param(name, value, splat) {
+      this.name = name;
+      this.value = value;
+      this.splat = splat;
+    }
+    Param.prototype.children = ['name', 'value'];
+    Param.prototype.compile = function(o) {
+      return this.name.compile(o, LEVEL_LIST);
+    };
+    Param.prototype.asReference = function(o) {
+      var node;
+      if (this.reference) {
+        return this.reference;
+      }
+      node = this.name;
+      if (node["this"]) {
+        node = node.properties[0].name;
+        if (node.value.reserved) {
+          node = new Literal('_' + node.value);
+        }
+      } else if (node.isComplex()) {
+        node = new Literal(o.scope.freeVariable('arg'));
+      }
+      node = new Value(node);
+      if (this.splat) {
+        node = new Splat(node);
+      }
+      return this.reference = node;
+    };
+    Param.prototype.isComplex = function() {
+      return this.name.isComplex();
+    };
+    return Param;
+  })();
+  exports.Splat = Splat = (function() {
+    __extends(Splat, Base);
+    Splat.prototype.children = ['name'];
+    Splat.prototype.isAssignable = YES;
+    function Splat(name) {
+      this.name = name.compile ? name : new Literal(name);
+    }
+    Splat.prototype.assigns = function(name) {
+      return this.name.assigns(name);
+    };
+    Splat.prototype.compile = function(o) {
+      if (this.index != null) {
+        return this.compileParam(o);
+      } else {
+        return this.name.compile(o);
+      }
+    };
+    Splat.compileSplattedArray = function(o, list, apply) {
+      var args, base, code, i, index, node, _len;
+      index = -1;
+      while ((node = list[++index]) && !(node instanceof Splat)) {
+        continue;
+      }
+      if (index >= list.length) {
+        return '';
+      }
+      if (list.length === 1) {
+        code = list[0].compile(o, LEVEL_LIST);
+        if (apply) {
+          return code;
+        }
+        return "" + (utility('slice')) + ".call(" + code + ")";
+      }
+      args = list.slice(index);
+      for (i = 0, _len = args.length; i < _len; i++) {
+        node = args[i];
+        code = node.compile(o, LEVEL_LIST);
+        args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]";
+      }
+      if (index === 0) {
+        return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")");
+      }
+      base = (function() {
+        var _i, _len2, _ref2, _results;
+        _ref2 = list.slice(0, index);
+        _results = [];
+        for (_i = 0, _len2 = _ref2.length; _i < _len2; _i++) {
+          node = _ref2[_i];
+          _results.push(node.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })();
+      return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")";
+    };
+    return Splat;
+  })();
+  exports.While = While = (function() {
+    __extends(While, Base);
+    function While(condition, options) {
+      this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
+      this.guard = options != null ? options.guard : void 0;
+    }
+    While.prototype.children = ['condition', 'guard', 'body'];
+    While.prototype.isStatement = YES;
+    While.prototype.makeReturn = function() {
+      this.returns = true;
+      return this;
+    };
+    While.prototype.addBody = function(body) {
+      this.body = body;
+      return this;
+    };
+    While.prototype.jumps = function() {
+      var expressions, node, _i, _len;
+      expressions = this.body.expressions;
+      if (!expressions.length) {
+        return false;
+      }
+      for (_i = 0, _len = expressions.length; _i < _len; _i++) {
+        node = expressions[_i];
+        if (node.jumps({
+          loop: true
+        })) {
+          return node;
+        }
+      }
+      return false;
+    };
+    While.prototype.compileNode = function(o) {
+      var body, code, rvar, set;
+      o.indent += TAB;
+      set = '';
+      body = this.body;
+      if (body.isEmpty()) {
+        body = '';
+      } else {
+        if (o.level > LEVEL_TOP || this.returns) {
+          rvar = o.scope.freeVariable('results');
+          set = "" + this.tab + rvar + " = [];\n";
+          if (body) {
+            body = Push.wrap(rvar, body);
+          }
+        }
+        if (this.guard) {
+          body = Block.wrap([new If(this.guard, body)]);
+        }
+        body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab;
+      }
+      code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}");
+      if (this.returns) {
+        code += "\n" + this.tab + "return " + rvar + ";";
+      }
+      return code;
+    };
+    return While;
+  })();
+  exports.Op = Op = (function() {
+    var CONVERSIONS, INVERSIONS;
+    __extends(Op, Base);
+    function Op(op, first, second, flip) {
+      var call;
+      if (op === 'in') {
+        return new In(first, second);
+      }
+      if (op === 'do') {
+        call = new Call(first, first.params || []);
+        call["do"] = true;
+        return call;
+      }
+      if (op === 'new') {
+        if (first instanceof Call && !first["do"] && !first.isNew) {
+          return first.newInstance();
+        }
+        if (first instanceof Code && first.bound || first["do"]) {
+          first = new Parens(first);
+        }
+      }
+      this.operator = CONVERSIONS[op] || op;
+      this.first = first;
+      this.second = second;
+      this.flip = !!flip;
+      return this;
+    }
+    CONVERSIONS = {
+      '==': '===',
+      '!=': '!==',
+      'of': 'in'
+    };
+    INVERSIONS = {
+      '!==': '===',
+      '===': '!=='
+    };
+    Op.prototype.children = ['first', 'second'];
+    Op.prototype.isSimpleNumber = NO;
+    Op.prototype.isUnary = function() {
+      return !this.second;
+    };
+    Op.prototype.isComplex = function() {
+      var _ref2;
+      return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex();
+    };
+    Op.prototype.isChainable = function() {
+      var _ref2;
+      return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!==';
+    };
+    Op.prototype.invert = function() {
+      var allInvertable, curr, fst, op, _ref2;
+      if (this.isChainable() && this.first.isChainable()) {
+        allInvertable = true;
+        curr = this;
+        while (curr && curr.operator) {
+          allInvertable && (allInvertable = curr.operator in INVERSIONS);
+          curr = curr.first;
+        }
+        if (!allInvertable) {
+          return new Parens(this).invert();
+        }
+        curr = this;
+        while (curr && curr.operator) {
+          curr.invert = !curr.invert;
+          curr.operator = INVERSIONS[curr.operator];
+          curr = curr.first;
+        }
+        return this;
+      } else if (op = INVERSIONS[this.operator]) {
+        this.operator = op;
+        if (this.first.unwrap() instanceof Op) {
+          this.first.invert();
+        }
+        return this;
+      } else if (this.second) {
+        return new Parens(this).invert();
+      } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) {
+        return fst;
+      } else {
+        return new Op('!', this);
+      }
+    };
+    Op.prototype.unfoldSoak = function(o) {
+      var _ref2;
+      return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first');
+    };
+    Op.prototype.compileNode = function(o) {
+      var code;
+      if (this.isUnary()) {
+        return this.compileUnary(o);
+      }
+      if (this.isChainable() && this.first.isChainable()) {
+        return this.compileChain(o);
+      }
+      if (this.operator === '?') {
+        return this.compileExistence(o);
+      }
+      this.first.front = this.front;
+      code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP);
+      if (o.level <= LEVEL_OP) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+    Op.prototype.compileChain = function(o) {
+      var code, fst, shared, _ref2;
+      _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1];
+      fst = this.first.compile(o, LEVEL_OP);
+      code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP));
+      return "(" + code + ")";
+    };
+    Op.prototype.compileExistence = function(o) {
+      var fst, ref;
+      if (this.first.isComplex()) {
+        ref = new Literal(o.scope.freeVariable('ref'));
+        fst = new Parens(new Assign(ref, this.first));
+      } else {
+        fst = this.first;
+        ref = fst;
+      }
+      return new If(new Existence(fst), ref, {
+        type: 'if'
+      }).addElse(this.second).compile(o);
+    };
+    Op.prototype.compileUnary = function(o) {
+      var op, parts;
+      parts = [op = this.operator];
+      if ((op === 'new' || op === 'typeof' || op === 'delete') || (op === '+' || op === '-') && this.first instanceof Op && this.first.operator === op) {
+        parts.push(' ');
+      }
+      if (op === 'new' && this.first.isStatement(o)) {
+        this.first = new Parens(this.first);
+      }
+      parts.push(this.first.compile(o, LEVEL_OP));
+      if (this.flip) {
+        parts.reverse();
+      }
+      return parts.join('');
+    };
+    Op.prototype.toString = function(idt) {
+      return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
+    };
+    return Op;
+  })();
+  exports.In = In = (function() {
+    __extends(In, Base);
+    function In(object, array) {
+      this.object = object;
+      this.array = array;
+    }
+    In.prototype.children = ['object', 'array'];
+    In.prototype.invert = NEGATE;
+    In.prototype.compileNode = function(o) {
+      var hasSplat, obj, _i, _len, _ref2;
+      if (this.array instanceof Value && this.array.isArray()) {
+        _ref2 = this.array.base.objects;
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          obj = _ref2[_i];
+          if (obj instanceof Splat) {
+            hasSplat = true;
+            break;
+          }
+        }
+        if (!hasSplat) {
+          return this.compileOrTest(o);
+        }
+      }
+      return this.compileLoopTest(o);
+    };
+    In.prototype.compileOrTest = function(o) {
+      var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3;
+      _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1];
+      _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];
+      tests = (function() {
+        var _len, _ref4, _results;
+        _ref4 = this.array.base.objects;
+        _results = [];
+        for (i = 0, _len = _ref4.length; i < _len; i++) {
+          item = _ref4[i];
+          _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_OP));
+        }
+        return _results;
+      }).call(this);
+      if (tests.length === 0) {
+        return 'false';
+      }
+      tests = tests.join(cnj);
+      if (o.level < LEVEL_OP) {
+        return tests;
+      } else {
+        return "(" + tests + ")";
+      }
+    };
+    In.prototype.compileLoopTest = function(o) {
+      var code, ref, sub, _ref2;
+      _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1];
+      code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0');
+      if (sub === ref) {
+        return code;
+      }
+      code = sub + ', ' + code;
+      if (o.level < LEVEL_LIST) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+    In.prototype.toString = function(idt) {
+      return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
+    };
+    return In;
+  })();
+  exports.Try = Try = (function() {
+    __extends(Try, Base);
+    function Try(attempt, error, recovery, ensure) {
+      this.attempt = attempt;
+      this.error = error;
+      this.recovery = recovery;
+      this.ensure = ensure;
+    }
+    Try.prototype.children = ['attempt', 'recovery', 'ensure'];
+    Try.prototype.isStatement = YES;
+    Try.prototype.jumps = function(o) {
+      var _ref2;
+      return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0);
+    };
+    Try.prototype.makeReturn = function() {
+      if (this.attempt) {
+        this.attempt = this.attempt.makeReturn();
+      }
+      if (this.recovery) {
+        this.recovery = this.recovery.makeReturn();
+      }
+      return this;
+    };
+    Try.prototype.compileNode = function(o) {
+      var catchPart, errorPart;
+      o.indent += TAB;
+      errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
+      catchPart = this.recovery ? (o.scope.add(this.error.value, 'param'), " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}") : !(this.ensure || this.recovery) ? ' catch (_e) {}' : void 0;
+      return ("" + this.tab + "try {\n" + (this.attempt.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" + (catchPart || '')) + (this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : '');
+    };
+    return Try;
+  })();
+  exports.Throw = Throw = (function() {
+    __extends(Throw, Base);
+    function Throw(expression) {
+      this.expression = expression;
+    }
+    Throw.prototype.children = ['expression'];
+    Throw.prototype.isStatement = YES;
+    Throw.prototype.jumps = NO;
+    Throw.prototype.makeReturn = THIS;
+    Throw.prototype.compileNode = function(o) {
+      return this.tab + ("throw " + (this.expression.compile(o)) + ";");
+    };
+    return Throw;
+  })();
+  exports.Existence = Existence = (function() {
+    __extends(Existence, Base);
+    function Existence(expression) {
+      this.expression = expression;
+    }
+    Existence.prototype.children = ['expression'];
+    Existence.prototype.invert = NEGATE;
+    Existence.prototype.compileNode = function(o) {
+      var cmp, cnj, code, _ref2;
+      code = this.expression.compile(o, LEVEL_OP);
+      code = IDENTIFIER.test(code) && !o.scope.check(code) ? ((_ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1], _ref2), "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null") : "" + code + " " + (this.negated ? '==' : '!=') + " null";
+      if (o.level <= LEVEL_COND) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+    return Existence;
+  })();
+  exports.Parens = Parens = (function() {
+    __extends(Parens, Base);
+    function Parens(body) {
+      this.body = body;
+    }
+    Parens.prototype.children = ['body'];
+    Parens.prototype.unwrap = function() {
+      return this.body;
+    };
+    Parens.prototype.isComplex = function() {
+      return this.body.isComplex();
+    };
+    Parens.prototype.makeReturn = function() {
+      return this.body.makeReturn();
+    };
+    Parens.prototype.compileNode = function(o) {
+      var bare, code, expr;
+      expr = this.body.unwrap();
+      if (expr instanceof Value && expr.isAtomic()) {
+        expr.front = this.front;
+        return expr.compile(o);
+      }
+      code = expr.compile(o, LEVEL_PAREN);
+      bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns));
+      if (bare) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+    return Parens;
+  })();
+  exports.For = For = (function() {
+    __extends(For, Base);
+    function For(body, source) {
+      var _ref2;
+      this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;
+      this.body = Block.wrap([body]);
+      this.own = !!source.own;
+      this.object = !!source.object;
+      if (this.object) {
+        _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1];
+      }
+      if (this.index instanceof Value) {
+        throw SyntaxError('index cannot be a pattern matching expression');
+      }
+      this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;
+      this.pattern = this.name instanceof Value;
+      if (this.range && this.index) {
+        throw SyntaxError('indexes do not apply to range loops');
+      }
+      if (this.range && this.pattern) {
+        throw SyntaxError('cannot pattern match over range loops');
+      }
+      this.returns = false;
+    }
+    For.prototype.children = ['body', 'source', 'guard', 'step'];
+    For.prototype.isStatement = YES;
+    For.prototype.jumps = While.prototype.jumps;
+    For.prototype.makeReturn = function() {
+      this.returns = true;
+      return this;
+    };
+    For.prototype.compileNode = function(o) {
+      var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2;
+      body = Block.wrap([this.body]);
+      lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0;
+      if (lastJumps && lastJumps instanceof Return) {
+        this.returns = false;
+      }
+      source = this.range ? this.source.base : this.source;
+      scope = o.scope;
+      name = this.name && this.name.compile(o, LEVEL_LIST);
+      index = this.index && this.index.compile(o, LEVEL_LIST);
+      if (name && !this.pattern) {
+        scope.find(name, {
+          immediate: true
+        });
+      }
+      if (index) {
+        scope.find(index, {
+          immediate: true
+        });
+      }
+      if (this.returns) {
+        rvar = scope.freeVariable('results');
+      }
+      ivar = (this.range ? name : index) || scope.freeVariable('i');
+      if (this.step && !this.range) {
+        stepvar = scope.freeVariable("step");
+      }
+      if (this.pattern) {
+        name = ivar;
+      }
+      varPart = '';
+      guardPart = '';
+      defPart = '';
+      idt1 = this.tab + TAB;
+      if (this.range) {
+        forPart = source.compile(merge(o, {
+          index: ivar,
+          step: this.step
+        }));
+      } else {
+        svar = this.source.compile(o, LEVEL_LIST);
+        if ((name || this.own) && !IDENTIFIER.test(svar)) {
+          defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n";
+          svar = ref;
+        }
+        if (name && !this.pattern) {
+          namePart = "" + name + " = " + svar + "[" + ivar + "]";
+        }
+        if (!this.object) {
+          lvar = scope.freeVariable('len');
+          forVarPart = ("" + ivar + " = 0, " + lvar + " = " + svar + ".length") + (this.step ? ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)) : '');
+          stepPart = this.step ? "" + ivar + " += " + stepvar : "" + ivar + "++";
+          forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart;
+        }
+      }
+      if (this.returns) {
+        resultPart = "" + this.tab + rvar + " = [];\n";
+        returnResult = "\n" + this.tab + "return " + rvar + ";";
+        body = Push.wrap(rvar, body);
+      }
+      if (this.guard) {
+        body = Block.wrap([new If(this.guard, body)]);
+      }
+      if (this.pattern) {
+        body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")));
+      }
+      defPart += this.pluckDirectCall(o, body);
+      if (namePart) {
+        varPart = "\n" + idt1 + namePart + ";";
+      }
+      if (this.object) {
+        forPart = "" + ivar + " in " + svar;
+        if (this.own) {
+          guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;";
+        }
+      }
+      body = body.compile(merge(o, {
+        indent: idt1
+      }), LEVEL_TOP);
+      if (body) {
+        body = '\n' + body + '\n';
+      }
+      return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || '');
+    };
+    For.prototype.pluckDirectCall = function(o, body) {
+      var base, defs, expr, fn, idx, ref, val, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
+      defs = '';
+      _ref2 = body.expressions;
+      for (idx = 0, _len = _ref2.length; idx < _len; idx++) {
+        expr = _ref2[idx];
+        expr = expr.unwrapAll();
+        if (!(expr instanceof Call)) {
+          continue;
+        }
+        val = expr.variable.unwrapAll();
+        if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) {
+          continue;
+        }
+        fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val;
+        ref = new Literal(o.scope.freeVariable('fn'));
+        base = new Value(ref);
+        if (val.base) {
+          _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];
+        }
+        body.expressions[idx] = new Call(base, expr.args);
+        defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
+      }
+      return defs;
+    };
+    return For;
+  })();
+  exports.Switch = Switch = (function() {
+    __extends(Switch, Base);
+    function Switch(subject, cases, otherwise) {
+      this.subject = subject;
+      this.cases = cases;
+      this.otherwise = otherwise;
+    }
+    Switch.prototype.children = ['subject', 'cases', 'otherwise'];
+    Switch.prototype.isStatement = YES;
+    Switch.prototype.jumps = function(o) {
+      var block, conds, _i, _len, _ref2, _ref3, _ref4;
+      if (o == null) {
+        o = {
+          block: true
+        };
+      }
+      _ref2 = this.cases;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1];
+        if (block.jumps(o)) {
+          return block;
+        }
+      }
+      return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0;
+    };
+    Switch.prototype.makeReturn = function() {
+      var pair, _i, _len, _ref2, _ref3;
+      _ref2 = this.cases;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        pair = _ref2[_i];
+        pair[1].makeReturn();
+      }
+      if ((_ref3 = this.otherwise) != null) {
+        _ref3.makeReturn();
+      }
+      return this;
+    };
+    Switch.prototype.compileNode = function(o) {
+      var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _len, _len2, _ref2, _ref3, _ref4, _ref5;
+      idt1 = o.indent + TAB;
+      idt2 = o.indent = idt1 + TAB;
+      code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n");
+      _ref3 = this.cases;
+      for (i = 0, _len = _ref3.length; i < _len; i++) {
+        _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1];
+        _ref5 = flatten([conditions]);
+        for (_i = 0, _len2 = _ref5.length; _i < _len2; _i++) {
+          cond = _ref5[_i];
+          if (!this.subject) {
+            cond = cond.invert();
+          }
+          code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n");
+        }
+        if (body = block.compile(o, LEVEL_TOP)) {
+          code += body + '\n';
+        }
+        if (i === this.cases.length - 1 && !this.otherwise) {
+          break;
+        }
+        expr = this.lastNonComment(block.expressions);
+        if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) {
+          continue;
+        }
+        code += idt2 + 'break;\n';
+      }
+      if (this.otherwise && this.otherwise.expressions.length) {
+        code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n");
+      }
+      return code + this.tab + '}';
+    };
+    return Switch;
+  })();
+  exports.If = If = (function() {
+    __extends(If, Base);
+    function If(condition, body, options) {
+      this.body = body;
+      if (options == null) {
+        options = {};
+      }
+      this.condition = options.type === 'unless' ? condition.invert() : condition;
+      this.elseBody = null;
+      this.isChain = false;
+      this.soak = options.soak;
+    }
+    If.prototype.children = ['condition', 'body', 'elseBody'];
+    If.prototype.bodyNode = function() {
+      var _ref2;
+      return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0;
+    };
+    If.prototype.elseBodyNode = function() {
+      var _ref2;
+      return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0;
+    };
+    If.prototype.addElse = function(elseBody) {
+      if (this.isChain) {
+        this.elseBodyNode().addElse(elseBody);
+      } else {
+        this.isChain = elseBody instanceof If;
+        this.elseBody = this.ensureBlock(elseBody);
+      }
+      return this;
+    };
+    If.prototype.isStatement = function(o) {
+      var _ref2;
+      return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0);
+    };
+    If.prototype.jumps = function(o) {
+      var _ref2;
+      return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0);
+    };
+    If.prototype.compileNode = function(o) {
+      if (this.isStatement(o)) {
+        return this.compileStatement(o);
+      } else {
+        return this.compileExpression(o);
+      }
+    };
+    If.prototype.makeReturn = function() {
+      this.body && (this.body = new Block([this.body.makeReturn()]));
+      this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn()]));
+      return this;
+    };
+    If.prototype.ensureBlock = function(node) {
+      if (node instanceof Block) {
+        return node;
+      } else {
+        return new Block([node]);
+      }
+    };
+    If.prototype.compileStatement = function(o) {
+      var body, child, cond, exeq, ifPart;
+      child = del(o, 'chainChild');
+      exeq = del(o, 'isExistentialEquals');
+      if (exeq) {
+        return new If(this.condition.invert(), this.elseBodyNode(), {
+          type: 'if'
+        }).compile(o);
+      }
+      cond = this.condition.compile(o, LEVEL_PAREN);
+      o.indent += TAB;
+      body = this.ensureBlock(this.body).compile(o);
+      if (body) {
+        body = "\n" + body + "\n" + this.tab;
+      }
+      ifPart = "if (" + cond + ") {" + body + "}";
+      if (!child) {
+        ifPart = this.tab + ifPart;
+      }
+      if (!this.elseBody) {
+        return ifPart;
+      }
+      return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}");
+    };
+    If.prototype.compileExpression = function(o) {
+      var alt, body, code, cond;
+      cond = this.condition.compile(o, LEVEL_COND);
+      body = this.bodyNode().compile(o, LEVEL_LIST);
+      alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0';
+      code = "" + cond + " ? " + body + " : " + alt;
+      if (o.level >= LEVEL_COND) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+    If.prototype.unfoldSoak = function() {
+      return this.soak && this;
+    };
+    return If;
+  })();
+  Push = {
+    wrap: function(name, exps) {
+      if (exps.isEmpty() || last(exps.expressions).jumps()) {
+        return exps;
+      }
+      return exps.push(new Call(new Value(new Literal(name), [new Access(new Literal('push'))]), [exps.pop()]));
+    }
+  };
+  Closure = {
+    wrap: function(expressions, statement, noReturn) {
+      var args, call, func, mentionsArgs, meth;
+      if (expressions.jumps()) {
+        return expressions;
+      }
+      func = new Code([], Block.wrap([expressions]));
+      args = [];
+      if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) {
+        meth = new Literal(mentionsArgs ? 'apply' : 'call');
+        args = [new Literal('this')];
+        if (mentionsArgs) {
+          args.push(new Literal('arguments'));
+        }
+        func = new Value(func, [new Access(meth)]);
+      }
+      func.noReturn = noReturn;
+      call = new Call(func, args);
+      if (statement) {
+        return Block.wrap([call]);
+      } else {
+        return call;
+      }
+    },
+    literalArgs: function(node) {
+      return node instanceof Literal && node.value === 'arguments' && !node.asKey;
+    },
+    literalThis: function(node) {
+      return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound);
+    }
+  };
+  unfoldSoak = function(o, parent, name) {
+    var ifn;
+    if (!(ifn = parent[name].unfoldSoak(o))) {
+      return;
+    }
+    parent[name] = ifn.body;
+    ifn.body = new Value(parent);
+    return ifn;
+  };
+  UTILITIES = {
+    "extends": 'function(child, parent) {\n  for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }\n  function ctor() { this.constructor = child; }\n  ctor.prototype = parent.prototype;\n  child.prototype = new ctor;\n  child.__super__ = parent.prototype;\n  return child;\n}',
+    bind: 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }',
+    indexOf: 'Array.prototype.indexOf || function(item) {\n  for (var i = 0, l = this.length; i < l; i++) {\n    if (this[i] === item) return i;\n  }\n  return -1;\n}',
+    hasProp: 'Object.prototype.hasOwnProperty',
+    slice: 'Array.prototype.slice'
+  };
+  LEVEL_TOP = 1;
+  LEVEL_PAREN = 2;
+  LEVEL_LIST = 3;
+  LEVEL_COND = 4;
+  LEVEL_OP = 5;
+  LEVEL_ACCESS = 6;
+  TAB = '  ';
+  IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
+  IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$");
+  SIMPLENUM = /^[+-]?\d+$/;
+  METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$");
+  IS_STRING = /^['"]/;
+  utility = function(name) {
+    var ref;
+    ref = "__" + name;
+    Scope.root.assign(ref, UTILITIES[name]);
+    return ref;
+  };
+  multident = function(code, tab) {
+    return code.replace(/\n/g, '$&' + tab);
+  };
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/optparse.js b/weinre.build/vendor/node_modules/coffee-script/lib/optparse.js
new file mode 100755
index 0000000..13841e5
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/optparse.js
@@ -0,0 +1,111 @@
+(function() {
+  var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
+  exports.OptionParser = OptionParser = (function() {
+    function OptionParser(rules, banner) {
+      this.banner = banner;
+      this.rules = buildRules(rules);
+    }
+    OptionParser.prototype.parse = function(args) {
+      var arg, i, isOption, matchedRule, options, rule, value, _i, _len, _len2, _ref;
+      options = {
+        arguments: [],
+        literals: []
+      };
+      args = normalizeArguments(args);
+      for (i = 0, _len = args.length; i < _len; i++) {
+        arg = args[i];
+        if (arg === '--') {
+          options.literals = args.slice(i + 1);
+          break;
+        }
+        isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
+        matchedRule = false;
+        _ref = this.rules;
+        for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
+          rule = _ref[_i];
+          if (rule.shortFlag === arg || rule.longFlag === arg) {
+            value = rule.hasArgument ? args[i += 1] : true;
+            options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
+            matchedRule = true;
+            break;
+          }
+        }
+        if (isOption && !matchedRule) {
+          throw new Error("unrecognized option: " + arg);
+        }
+        if (!isOption) {
+          options.arguments = args.slice(i);
+          break;
+        }
+      }
+      return options;
+    };
+    OptionParser.prototype.help = function() {
+      var letPart, lines, rule, spaces, _i, _len, _ref;
+      lines = [];
+      if (this.banner) {
+        lines.unshift("" + this.banner + "\n");
+      }
+      _ref = this.rules;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        rule = _ref[_i];
+        spaces = 15 - rule.longFlag.length;
+        spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
+        letPart = rule.shortFlag ? rule.shortFlag + ', ' : '    ';
+        lines.push('  ' + letPart + rule.longFlag + spaces + rule.description);
+      }
+      return "\n" + (lines.join('\n')) + "\n";
+    };
+    return OptionParser;
+  })();
+  LONG_FLAG = /^(--\w[\w\-]+)/;
+  SHORT_FLAG = /^(-\w)/;
+  MULTI_FLAG = /^-(\w{2,})/;
+  OPTIONAL = /\[(\w+(\*?))\]/;
+  buildRules = function(rules) {
+    var tuple, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = rules.length; _i < _len; _i++) {
+      tuple = rules[_i];
+      if (tuple.length < 3) {
+        tuple.unshift(null);
+      }
+      _results.push(buildRule.apply(null, tuple));
+    }
+    return _results;
+  };
+  buildRule = function(shortFlag, longFlag, description, options) {
+    var match;
+    if (options == null) {
+      options = {};
+    }
+    match = longFlag.match(OPTIONAL);
+    longFlag = longFlag.match(LONG_FLAG)[1];
+    return {
+      name: longFlag.substr(2),
+      shortFlag: shortFlag,
+      longFlag: longFlag,
+      description: description,
+      hasArgument: !!(match && match[1]),
+      isList: !!(match && match[2])
+    };
+  };
+  normalizeArguments = function(args) {
+    var arg, l, match, result, _i, _j, _len, _len2, _ref;
+    args = args.slice(0);
+    result = [];
+    for (_i = 0, _len = args.length; _i < _len; _i++) {
+      arg = args[_i];
+      if (match = arg.match(MULTI_FLAG)) {
+        _ref = match[1].split('');
+        for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
+          l = _ref[_j];
+          result.push('-' + l);
+        }
+      } else {
+        result.push(arg);
+      }
+    }
+    return result;
+  };
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/parser.js b/weinre.build/vendor/node_modules/coffee-script/lib/parser.js
new file mode 100755
index 0000000..789e8ca
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/parser.js
@@ -0,0 +1,676 @@
+/* Jison generated parser */
+var parser = (function(){
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Throw":11,"Comment":12,"STATEMENT":13,"Value":14,"Invocation":15,"Code":16,"Operation":17,"Assign":18,"If":19,"Try":20,"While":21,"For":22,"Switch":23,"Class":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"BOOL":35,"Assignable":36,"=":37,"AssignObj":38,"ObjAssignable":39,":":40,"ThisProperty":41,"RETURN":42,"HERECOMMENT":43,"PARAM_START":44,"ParamList":45,"PARAM_END":46,"FuncGlyph":47,"->":48,"=>":49,"OptComma":50,",":51,"Param":52,"ParamVar":53,"...":54,"Array":55,"Object":56,"Splat":57,"SimpleAssignable":58,"Accessor":59,"Parenthetical":60,"Range":61,"This":62,".":63,"?.":64,"::":65,"Index":66,"INDEX_START":67,"IndexValue":68,"INDEX_END":69,"INDEX_SOAK":70,"INDEX_PROTO":71,"Slice":72,"{":73,"AssignList":74,"}":75,"CLASS":76,"EXTENDS":77,"OptFuncExist":78,"Arguments":79,"SUPER":80,"FUNC_EXIST":81,"CALL_START":82,"CALL_END":83,"ArgList":84,"THIS":85,"@":86,"[":87,"]":88,"RangeDots":89,"..":90,"Arg":91,"SimpleArgs":92,"TRY":93,"Catch":94,"FINALLY":95,"CATCH":96,"THROW":97,"(":98,")":99,"WhileSource":100,"WHILE":101,"WHEN":102,"UNTIL":103,"Loop":104,"LOOP":105,"ForBody":106,"FOR":107,"ForStart":108,"ForSource":109,"ForVariables":110,"OWN":111,"ForValue":112,"FORIN":113,"FOROF":114,"BY":115,"SWITCH":116,"Whens":117,"ELSE":118,"When":119,"LEADING_WHEN":120,"IfBlock":121,"IF":122,"POST_IF":123,"UNARY":124,"-":125,"+":126,"--":127,"++":128,"?":129,"MATH":130,"SHIFT":131,"COMPARE":132,"LOGIC":133,"RELATION":134,"COMPOUND_ASSIGN":135,"$accept":0,"$end":1},
+terminals_: {2:"error",6:"TERMINATOR",13:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"BOOL",37:"=",40:":",42:"RETURN",43:"HERECOMMENT",44:"PARAM_START",46:"PARAM_END",48:"->",49:"=>",51:",",54:"...",63:".",64:"?.",65:"::",67:"INDEX_START",69:"INDEX_END",70:"INDEX_SOAK",71:"INDEX_PROTO",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"},
+productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[18,3],[18,5],[38,1],[38,3],[38,5],[38,1],[39,1],[39,1],[39,1],[10,2],[10,1],[12,1],[16,5],[16,2],[47,1],[47,1],[50,0],[50,1],[45,0],[45,1],[45,3],[52,1],[52,2],[52,3],[53,1],[53,1],[53,1],[53,1],[57,2],[58,1],[58,2],[58,2],[58,1],[36,1],[36,1],[36,1],[14,1],[14,1],[14,1],[14,1],[14,1],[59,2],[59,2],[59,2],[59,1],[59,1],[66,3],[66,2],[66,2],[68,1],[68,1],[56,4],[74,0],[74,1],[74,3],[74,4],[74,6],[24,1],[24,2],[24,3],[24,4],[24,2],[24,3],[24,4],[24,5],[15,3],[15,3],[15,1],[15,2],[78,0],[78,1],[79,2],[79,4],[62,1],[62,1],[41,2],[55,2],[55,4],[89,1],[89,1],[61,5],[72,3],[72,2],[72,2],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[20,2],[20,3],[20,4],[20,5],[94,3],[11,2],[60,3],[60,5],[100,2],[100,4],[100,2],[100,4],[21,2],[21,2],[21,2],[21,1],[104,2],[104,2],[22,2],[22,2],[22,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[23,5],[23,7],[23,4],[23,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[19,1],[19,3],[19,3],[19,3],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,5],[17,3]],
+performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1:return this.$ = new yy.Block;
+break;
+case 2:return this.$ = $$[$0];
+break;
+case 3:return this.$ = $$[$0-1];
+break;
+case 4:this.$ = yy.Block.wrap([$$[$0]]);
+break;
+case 5:this.$ = $$[$0-2].push($$[$0]);
+break;
+case 6:this.$ = $$[$0-1];
+break;
+case 7:this.$ = $$[$0];
+break;
+case 8:this.$ = $$[$0];
+break;
+case 9:this.$ = $$[$0];
+break;
+case 10:this.$ = $$[$0];
+break;
+case 11:this.$ = $$[$0];
+break;
+case 12:this.$ = new yy.Literal($$[$0]);
+break;
+case 13:this.$ = $$[$0];
+break;
+case 14:this.$ = $$[$0];
+break;
+case 15:this.$ = $$[$0];
+break;
+case 16:this.$ = $$[$0];
+break;
+case 17:this.$ = $$[$0];
+break;
+case 18:this.$ = $$[$0];
+break;
+case 19:this.$ = $$[$0];
+break;
+case 20:this.$ = $$[$0];
+break;
+case 21:this.$ = $$[$0];
+break;
+case 22:this.$ = $$[$0];
+break;
+case 23:this.$ = $$[$0];
+break;
+case 24:this.$ = new yy.Block;
+break;
+case 25:this.$ = $$[$0-1];
+break;
+case 26:this.$ = new yy.Literal($$[$0]);
+break;
+case 27:this.$ = new yy.Literal($$[$0]);
+break;
+case 28:this.$ = new yy.Literal($$[$0]);
+break;
+case 29:this.$ = $$[$0];
+break;
+case 30:this.$ = new yy.Literal($$[$0]);
+break;
+case 31:this.$ = new yy.Literal($$[$0]);
+break;
+case 32:this.$ = (function () {
+        var val;
+        val = new yy.Literal($$[$0]);
+        if ($$[$0] === 'undefined') {
+          val.isUndefined = true;
+        }
+        return val;
+      }());
+break;
+case 33:this.$ = new yy.Assign($$[$0-2], $$[$0]);
+break;
+case 34:this.$ = new yy.Assign($$[$0-4], $$[$0-1]);
+break;
+case 35:this.$ = new yy.Value($$[$0]);
+break;
+case 36:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object');
+break;
+case 37:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object');
+break;
+case 38:this.$ = $$[$0];
+break;
+case 39:this.$ = $$[$0];
+break;
+case 40:this.$ = $$[$0];
+break;
+case 41:this.$ = $$[$0];
+break;
+case 42:this.$ = new yy.Return($$[$0]);
+break;
+case 43:this.$ = new yy.Return;
+break;
+case 44:this.$ = new yy.Comment($$[$0]);
+break;
+case 45:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]);
+break;
+case 46:this.$ = new yy.Code([], $$[$0], $$[$0-1]);
+break;
+case 47:this.$ = 'func';
+break;
+case 48:this.$ = 'boundfunc';
+break;
+case 49:this.$ = $$[$0];
+break;
+case 50:this.$ = $$[$0];
+break;
+case 51:this.$ = [];
+break;
+case 52:this.$ = [$$[$0]];
+break;
+case 53:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 54:this.$ = new yy.Param($$[$0]);
+break;
+case 55:this.$ = new yy.Param($$[$0-1], null, true);
+break;
+case 56:this.$ = new yy.Param($$[$0-2], $$[$0]);
+break;
+case 57:this.$ = $$[$0];
+break;
+case 58:this.$ = $$[$0];
+break;
+case 59:this.$ = $$[$0];
+break;
+case 60:this.$ = $$[$0];
+break;
+case 61:this.$ = new yy.Splat($$[$0-1]);
+break;
+case 62:this.$ = new yy.Value($$[$0]);
+break;
+case 63:this.$ = $$[$0-1].push($$[$0]);
+break;
+case 64:this.$ = new yy.Value($$[$0-1], [$$[$0]]);
+break;
+case 65:this.$ = $$[$0];
+break;
+case 66:this.$ = $$[$0];
+break;
+case 67:this.$ = new yy.Value($$[$0]);
+break;
+case 68:this.$ = new yy.Value($$[$0]);
+break;
+case 69:this.$ = $$[$0];
+break;
+case 70:this.$ = new yy.Value($$[$0]);
+break;
+case 71:this.$ = new yy.Value($$[$0]);
+break;
+case 72:this.$ = new yy.Value($$[$0]);
+break;
+case 73:this.$ = $$[$0];
+break;
+case 74:this.$ = new yy.Access($$[$0]);
+break;
+case 75:this.$ = new yy.Access($$[$0], 'soak');
+break;
+case 76:this.$ = new yy.Access($$[$0], 'proto');
+break;
+case 77:this.$ = new yy.Access(new yy.Literal('prototype'));
+break;
+case 78:this.$ = $$[$0];
+break;
+case 79:this.$ = $$[$0-1];
+break;
+case 80:this.$ = yy.extend($$[$0], {
+          soak: true
+        });
+break;
+case 81:this.$ = yy.extend($$[$0], {
+          proto: true
+        });
+break;
+case 82:this.$ = new yy.Index($$[$0]);
+break;
+case 83:this.$ = new yy.Slice($$[$0]);
+break;
+case 84:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated);
+break;
+case 85:this.$ = [];
+break;
+case 86:this.$ = [$$[$0]];
+break;
+case 87:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 88:this.$ = $$[$0-3].concat($$[$0]);
+break;
+case 89:this.$ = $$[$0-5].concat($$[$0-2]);
+break;
+case 90:this.$ = new yy.Class;
+break;
+case 91:this.$ = new yy.Class(null, null, $$[$0]);
+break;
+case 92:this.$ = new yy.Class(null, $$[$0]);
+break;
+case 93:this.$ = new yy.Class(null, $$[$0-1], $$[$0]);
+break;
+case 94:this.$ = new yy.Class($$[$0]);
+break;
+case 95:this.$ = new yy.Class($$[$0-1], null, $$[$0]);
+break;
+case 96:this.$ = new yy.Class($$[$0-2], $$[$0]);
+break;
+case 97:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]);
+break;
+case 98:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 99:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 100:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]);
+break;
+case 101:this.$ = new yy.Call('super', $$[$0]);
+break;
+case 102:this.$ = false;
+break;
+case 103:this.$ = true;
+break;
+case 104:this.$ = [];
+break;
+case 105:this.$ = $$[$0-2];
+break;
+case 106:this.$ = new yy.Value(new yy.Literal('this'));
+break;
+case 107:this.$ = new yy.Value(new yy.Literal('this'));
+break;
+case 108:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this');
+break;
+case 109:this.$ = new yy.Arr([]);
+break;
+case 110:this.$ = new yy.Arr($$[$0-2]);
+break;
+case 111:this.$ = 'inclusive';
+break;
+case 112:this.$ = 'exclusive';
+break;
+case 113:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]);
+break;
+case 114:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 115:this.$ = new yy.Range($$[$0-1], null, $$[$0]);
+break;
+case 116:this.$ = new yy.Range(null, $$[$0], $$[$0-1]);
+break;
+case 117:this.$ = [$$[$0]];
+break;
+case 118:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 119:this.$ = $$[$0-3].concat($$[$0]);
+break;
+case 120:this.$ = $$[$0-2];
+break;
+case 121:this.$ = $$[$0-5].concat($$[$0-2]);
+break;
+case 122:this.$ = $$[$0];
+break;
+case 123:this.$ = $$[$0];
+break;
+case 124:this.$ = $$[$0];
+break;
+case 125:this.$ = [].concat($$[$0-2], $$[$0]);
+break;
+case 126:this.$ = new yy.Try($$[$0]);
+break;
+case 127:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]);
+break;
+case 128:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]);
+break;
+case 129:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]);
+break;
+case 130:this.$ = [$$[$0-1], $$[$0]];
+break;
+case 131:this.$ = new yy.Throw($$[$0]);
+break;
+case 132:this.$ = new yy.Parens($$[$0-1]);
+break;
+case 133:this.$ = new yy.Parens($$[$0-2]);
+break;
+case 134:this.$ = new yy.While($$[$0]);
+break;
+case 135:this.$ = new yy.While($$[$0-2], {
+          guard: $$[$0]
+        });
+break;
+case 136:this.$ = new yy.While($$[$0], {
+          invert: true
+        });
+break;
+case 137:this.$ = new yy.While($$[$0-2], {
+          invert: true,
+          guard: $$[$0]
+        });
+break;
+case 138:this.$ = $$[$0-1].addBody($$[$0]);
+break;
+case 139:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+break;
+case 140:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+break;
+case 141:this.$ = $$[$0];
+break;
+case 142:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]);
+break;
+case 143:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]]));
+break;
+case 144:this.$ = new yy.For($$[$0-1], $$[$0]);
+break;
+case 145:this.$ = new yy.For($$[$0-1], $$[$0]);
+break;
+case 146:this.$ = new yy.For($$[$0], $$[$0-1]);
+break;
+case 147:this.$ = {
+          source: new yy.Value($$[$0])
+        };
+break;
+case 148:this.$ = (function () {
+        $$[$0].own = $$[$0-1].own;
+        $$[$0].name = $$[$0-1][0];
+        $$[$0].index = $$[$0-1][1];
+        return $$[$0];
+      }());
+break;
+case 149:this.$ = $$[$0];
+break;
+case 150:this.$ = (function () {
+        $$[$0].own = true;
+        return $$[$0];
+      }());
+break;
+case 151:this.$ = $$[$0];
+break;
+case 152:this.$ = new yy.Value($$[$0]);
+break;
+case 153:this.$ = new yy.Value($$[$0]);
+break;
+case 154:this.$ = [$$[$0]];
+break;
+case 155:this.$ = [$$[$0-2], $$[$0]];
+break;
+case 156:this.$ = {
+          source: $$[$0]
+        };
+break;
+case 157:this.$ = {
+          source: $$[$0],
+          object: true
+        };
+break;
+case 158:this.$ = {
+          source: $$[$0-2],
+          guard: $$[$0]
+        };
+break;
+case 159:this.$ = {
+          source: $$[$0-2],
+          guard: $$[$0],
+          object: true
+        };
+break;
+case 160:this.$ = {
+          source: $$[$0-2],
+          step: $$[$0]
+        };
+break;
+case 161:this.$ = {
+          source: $$[$0-4],
+          guard: $$[$0-2],
+          step: $$[$0]
+        };
+break;
+case 162:this.$ = {
+          source: $$[$0-4],
+          step: $$[$0-2],
+          guard: $$[$0]
+        };
+break;
+case 163:this.$ = new yy.Switch($$[$0-3], $$[$0-1]);
+break;
+case 164:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]);
+break;
+case 165:this.$ = new yy.Switch(null, $$[$0-1]);
+break;
+case 166:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]);
+break;
+case 167:this.$ = $$[$0];
+break;
+case 168:this.$ = $$[$0-1].concat($$[$0]);
+break;
+case 169:this.$ = [[$$[$0-1], $$[$0]]];
+break;
+case 170:this.$ = [[$$[$0-2], $$[$0-1]]];
+break;
+case 171:this.$ = new yy.If($$[$0-1], $$[$0], {
+          type: $$[$0-2]
+        });
+break;
+case 172:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], {
+          type: $$[$0-2]
+        }));
+break;
+case 173:this.$ = $$[$0];
+break;
+case 174:this.$ = $$[$0-2].addElse($$[$0]);
+break;
+case 175:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+          type: $$[$0-1],
+          statement: true
+        });
+break;
+case 176:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+          type: $$[$0-1],
+          statement: true
+        });
+break;
+case 177:this.$ = new yy.Op($$[$0-1], $$[$0]);
+break;
+case 178:this.$ = new yy.Op('-', $$[$0]);
+break;
+case 179:this.$ = new yy.Op('+', $$[$0]);
+break;
+case 180:this.$ = new yy.Op('--', $$[$0]);
+break;
+case 181:this.$ = new yy.Op('++', $$[$0]);
+break;
+case 182:this.$ = new yy.Op('--', $$[$0-1], null, true);
+break;
+case 183:this.$ = new yy.Op('++', $$[$0-1], null, true);
+break;
+case 184:this.$ = new yy.Existence($$[$0-1]);
+break;
+case 185:this.$ = new yy.Op('+', $$[$0-2], $$[$0]);
+break;
+case 186:this.$ = new yy.Op('-', $$[$0-2], $$[$0]);
+break;
+case 187:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 188:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 189:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 190:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 191:this.$ = (function () {
+        if ($$[$0-1].charAt(0) === '!') {
+          return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();
+        } else {
+          return new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+        }
+      }());
+break;
+case 192:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 193:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]);
+break;
+case 194:this.$ = new yy.Extends($$[$0-2], $$[$0]);
+break;
+}
+},
+table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,5],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,71]},{6:[1,72]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:74,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[1,73],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:87,101:[1,62],103:[1,63],106:88,107:[1,65],108:66,123:[1,86]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],46:[2,13],51:[2,13],54:[2,13],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,13],70:[1,97],71:[1,98],75:[2,13],78:89,81:[1,91],82:[2,102],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],46:[2,14],51:[2,14],54:[2,14],59:100,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,14],70:[1,97],71:[1,98],75:[2,14],78:99,81:[1,91],82:[2,102],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],46:[2,15],51:[2,15],54:[2,15],69:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],46:[2,16],51:[2,16],54:[2,16],69:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],46:[2,17],51:[2,17],54:[2,17],69:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],46:[2,18],51:[2,18],54:[2,18],69:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],46:[2,19],51:[2,19],54:[2,19],69:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],46:[2,20],51:[2,20],54:[2,20],69:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],46:[2,21],51:[2,21],54:[2,21],69:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],46:[2,22],51:[2,22],54:[2,22],69:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],46:[2,23],51:[2,23],54:[2,23],69:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,12],6:[2,12],26:[2,12],99:[2,12],101:[2,12],103:[2,12],107:[2,12],123:[2,12]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],37:[1,101],46:[2,69],51:[2,69],54:[2,69],63:[2,69],64:[2,69],65:[2,69],67:[2,69],69:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],46:[2,70],51:[2,70],54:[2,70],63:[2,70],64:[2,70],65:[2,70],67:[2,70],69:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],46:[2,71],51:[2,71],54:[2,71],63:[2,71],64:[2,71],65:[2,71],67:[2,71],69:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],46:[2,72],51:[2,72],54:[2,72],63:[2,72],64:[2,72],65:[2,72],67:[2,72],69:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],46:[2,73],51:[2,73],54:[2,73],63:[2,73],64:[2,73],65:[2,73],67:[2,73],69:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],46:[2,100],51:[2,100],54:[2,100],63:[2,100],64:[2,100],65:[2,100],67:[2,100],69:[2,100],70:[2,100],71:[2,100],75:[2,100],79:102,81:[2,100],82:[1,103],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{27:107,28:[1,70],41:108,45:104,46:[2,51],51:[2,51],52:105,53:106,55:109,56:110,73:[1,67],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{14:119,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:118,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{14:119,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:122,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],37:[2,66],46:[2,66],51:[2,66],54:[2,66],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[1,126],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[1,123],128:[1,124],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[1,125]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],46:[2,173],51:[2,173],54:[2,173],69:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[1,127],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],46:[2,141],51:[2,141],54:[2,141],69:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{5:130,25:[1,5]},{8:131,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,132],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,90],5:133,6:[2,90],14:119,15:120,25:[1,5],26:[2,90],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,46:[2,90],51:[2,90],54:[2,90],55:47,56:48,58:135,60:25,61:26,62:27,69:[2,90],73:[1,67],75:[2,90],77:[1,134],80:[1,28],83:[2,90],85:[1,55],86:[1,56],87:[1,54],88:[2,90],90:[2,90],98:[1,53],99:[2,90],101:[2,90],102:[2,90],103:[2,90],107:[2,90],115:[2,90],123:[2,90],125:[2,90],126:[2,90],129:[2,90],130:[2,90],131:[2,90],132:[2,90],133:[2,90],134:[2,90]},{1:[2,43],6:[2,43],8:136,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[2,43],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],99:[2,43],100:39,101:[2,43],103:[2,43],104:40,105:[1,64],106:41,107:[2,43],108:66,116:[1,42],121:37,122:[1,61],123:[2,43],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:137,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,44],6:[2,44],25:[2,44],26:[2,44],51:[2,44],75:[2,44],99:[2,44],101:[2,44],103:[2,44],107:[2,44],123:[2,44]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],37:[2,67],46:[2,67],51:[2,67],54:[2,67],63:[2,67],64:[2,67],65:[2,67],67:[2,67],69:[2,67],70:[2,67],71:[2,67],75:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],37:[2,68],46:[2,68],51:[2,68],54:[2,68],63:[2,68],64:[2,68],65:[2,68],67:[2,68],69:[2,68],70:[2,68],71:[2,68],75:[2,68],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],46:[2,29],51:[2,29],54:[2,29],63:[2,29],64:[2,29],65:[2,29],67:[2,29],69:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],46:[2,30],51:[2,30],54:[2,30],63:[2,30],64:[2,30],65:[2,30],67:[2,30],69:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],46:[2,31],51:[2,31],54:[2,31],63:[2,31],64:[2,31],65:[2,31],67:[2,31],69:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],46:[2,32],51:[2,32],54:[2,32],63:[2,32],64:[2,32],65:[2,32],67:[2,32],69:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{4:138,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,139],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:142,85:[1,55],86:[1,56],87:[1,54],88:[1,141],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],46:[2,106],51:[2,106],54:[2,106],63:[2,106],64:[2,106],65:[2,106],67:[2,106],69:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],27:146,28:[1,70],46:[2,107],51:[2,107],54:[2,107],63:[2,107],64:[2,107],65:[2,107],67:[2,107],69:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{25:[2,47]},{25:[2,48]},{1:[2,62],6:[2,62],25:[2,62],26:[2,62],37:[2,62],46:[2,62],51:[2,62],54:[2,62],63:[2,62],64:[2,62],65:[2,62],67:[2,62],69:[2,62],70:[2,62],71:[2,62],75:[2,62],77:[2,62],81:[2,62],82:[2,62],83:[2,62],88:[2,62],90:[2,62],99:[2,62],101:[2,62],102:[2,62],103:[2,62],107:[2,62],115:[2,62],123:[2,62],125:[2,62],126:[2,62],127:[2,62],128:[2,62],129:[2,62],130:[2,62],131:[2,62],132:[2,62],133:[2,62],134:[2,62],135:[2,62]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],37:[2,65],46:[2,65],51:[2,65],54:[2,65],63:[2,65],64:[2,65],65:[2,65],67:[2,65],69:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{8:147,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,5],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,70],55:157,56:158,61:152,73:[1,67],87:[1,54],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,85],12:165,25:[2,85],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:163,39:164,41:168,43:[1,46],51:[2,85],74:162,75:[2,85],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],40:[2,27],46:[2,27],51:[2,27],54:[2,27],63:[2,27],64:[2,27],65:[2,27],67:[2,27],69:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],40:[2,28],46:[2,28],51:[2,28],54:[2,28],63:[2,28],64:[2,28],65:[2,28],67:[2,28],69:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],37:[2,26],40:[2,26],46:[2,26],51:[2,26],54:[2,26],63:[2,26],64:[2,26],65:[2,26],67:[2,26],69:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[2,6],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],99:[2,6],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],46:[2,24],51:[2,24],54:[2,24],69:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,71],26:[1,170]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],46:[2,184],51:[2,184],54:[2,184],69:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{8:171,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],46:[2,140],51:[2,140],54:[2,140],69:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],46:[2,145],51:[2,145],54:[2,145],69:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],101:[2,145],102:[2,145],103:[2,145],107:[2,145],115:[2,145],123:[2,145],125:[2,145],126:[2,145],129:[2,145],130:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145]},{8:179,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],46:[2,139],51:[2,139],54:[2,139],69:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],101:[2,139],102:[2,139],103:[2,139],107:[2,139],115:[2,139],123:[2,139],125:[2,139],126:[2,139],129:[2,139],130:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],46:[2,144],51:[2,144],54:[2,144],69:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],101:[2,144],102:[2,144],103:[2,144],107:[2,144],115:[2,144],123:[2,144],125:[2,144],126:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144]},{79:180,82:[1,103]},{1:[2,63],6:[2,63],25:[2,63],26:[2,63],37:[2,63],46:[2,63],51:[2,63],54:[2,63],63:[2,63],64:[2,63],65:[2,63],67:[2,63],69:[2,63],70:[2,63],71:[2,63],75:[2,63],77:[2,63],81:[2,63],82:[2,63],83:[2,63],88:[2,63],90:[2,63],99:[2,63],101:[2,63],102:[2,63],103:[2,63],107:[2,63],115:[2,63],123:[2,63],125:[2,63],126:[2,63],127:[2,63],128:[2,63],129:[2,63],130:[2,63],131:[2,63],132:[2,63],133:[2,63],134:[2,63],135:[2,63]},{82:[2,103]},{27:181,28:[1,70]},{27:182,28:[1,70]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],27:183,28:[1,70],37:[2,77],46:[2,77],51:[2,77],54:[2,77],63:[2,77],64:[2,77],65:[2,77],67:[2,77],69:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],37:[2,78],46:[2,78],51:[2,78],54:[2,78],63:[2,78],64:[2,78],65:[2,78],67:[2,78],69:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{8:185,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],54:[1,189],55:47,56:48,58:36,60:25,61:26,62:27,68:184,72:186,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],89:187,90:[1,188],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{66:190,67:[1,96],70:[1,97],71:[1,98]},{66:191,67:[1,96],70:[1,97],71:[1,98]},{79:192,82:[1,103]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],37:[2,64],46:[2,64],51:[2,64],54:[2,64],63:[2,64],64:[2,64],65:[2,64],67:[2,64],69:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{8:193,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,194],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],46:[2,101],51:[2,101],54:[2,101],63:[2,101],64:[2,101],65:[2,101],67:[2,101],69:[2,101],70:[2,101],71:[2,101],75:[2,101],81:[2,101],82:[2,101],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{46:[1,198],51:[1,199]},{46:[2,52],51:[2,52]},{37:[1,201],46:[2,54],51:[2,54],54:[1,200]},{37:[2,57],46:[2,57],51:[2,57],54:[2,57]},{37:[2,58],46:[2,58],51:[2,58],54:[2,58]},{37:[2,59],46:[2,59],51:[2,59],54:[2,59]},{37:[2,60],46:[2,60],51:[2,60],54:[2,60]},{27:146,28:[1,70]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:142,85:[1,55],86:[1,56],87:[1,54],88:[1,141],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],46:[2,46],51:[2,46],54:[2,46],69:[2,46],75:[2,46],83:[2,46],88:[2,46],90:[2,46],99:[2,46],101:[2,46],102:[2,46],103:[2,46],107:[2,46],115:[2,46],123:[2,46],125:[2,46],126:[2,46],129:[2,46],130:[2,46],131:[2,46],132:[2,46],133:[2,46],134:[2,46]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],46:[2,177],51:[2,177],54:[2,177],69:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:84,101:[2,177],102:[2,177],103:[2,177],106:85,107:[2,177],108:66,115:[2,177],123:[2,177],125:[2,177],126:[2,177],129:[1,75],130:[2,177],131:[2,177],132:[2,177],133:[2,177],134:[2,177]},{100:87,101:[1,62],103:[1,63],106:88,107:[1,65],108:66,123:[1,86]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],46:[2,178],51:[2,178],54:[2,178],69:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:84,101:[2,178],102:[2,178],103:[2,178],106:85,107:[2,178],108:66,115:[2,178],123:[2,178],125:[2,178],126:[2,178],129:[1,75],130:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],46:[2,179],51:[2,179],54:[2,179],69:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:84,101:[2,179],102:[2,179],103:[2,179],106:85,107:[2,179],108:66,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,75],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],46:[2,180],51:[2,180],54:[2,180],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,180],70:[2,66],71:[2,66],75:[2,180],81:[2,66],82:[2,66],83:[2,180],88:[2,180],90:[2,180],99:[2,180],101:[2,180],102:[2,180],103:[2,180],107:[2,180],115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[2,180],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],70:[1,97],71:[1,98],78:89,81:[1,91],82:[2,102]},{59:100,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],70:[1,97],71:[1,98],78:99,81:[1,91],82:[2,102]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],46:[2,69],51:[2,69],54:[2,69],63:[2,69],64:[2,69],65:[2,69],67:[2,69],69:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],46:[2,181],51:[2,181],54:[2,181],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,181],70:[2,66],71:[2,66],75:[2,181],81:[2,66],82:[2,66],83:[2,181],88:[2,181],90:[2,181],99:[2,181],101:[2,181],102:[2,181],103:[2,181],107:[2,181],115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[2,181],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],46:[2,182],51:[2,182],54:[2,182],69:[2,182],75:[2,182],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],46:[2,183],51:[2,183],54:[2,183],69:[2,183],75:[2,183],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{8:202,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,203],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,126],6:[2,126],25:[2,126],26:[2,126],46:[2,126],51:[2,126],54:[2,126],69:[2,126],75:[2,126],83:[2,126],88:[2,126],90:[2,126],94:207,95:[1,208],96:[1,209],99:[2,126],101:[2,126],102:[2,126],103:[2,126],107:[2,126],115:[2,126],123:[2,126],125:[2,126],126:[2,126],129:[2,126],130:[2,126],131:[2,126],132:[2,126],133:[2,126],134:[2,126]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],46:[2,138],51:[2,138],54:[2,138],69:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],101:[2,138],102:[2,138],103:[2,138],107:[2,138],115:[2,138],123:[2,138],125:[2,138],126:[2,138],129:[2,138],130:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],46:[2,146],51:[2,146],54:[2,146],69:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{25:[1,210],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{117:211,119:212,120:[1,213]},{1:[2,91],6:[2,91],25:[2,91],26:[2,91],46:[2,91],51:[2,91],54:[2,91],69:[2,91],75:[2,91],83:[2,91],88:[2,91],90:[2,91],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{14:214,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:215,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,94],5:216,6:[2,94],25:[1,5],26:[2,94],46:[2,94],51:[2,94],54:[2,94],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,94],70:[2,66],71:[2,66],75:[2,94],77:[1,217],81:[2,66],82:[2,66],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,42],6:[2,42],26:[2,42],99:[2,42],100:84,101:[2,42],103:[2,42],106:85,107:[2,42],108:66,123:[2,42],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,131],6:[2,131],26:[2,131],99:[2,131],100:84,101:[2,131],103:[2,131],106:85,107:[2,131],108:66,123:[2,131],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,71],99:[1,218]},{4:219,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,122],25:[2,122],51:[2,122],54:[1,221],88:[2,122],89:220,90:[1,188],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],37:[2,109],46:[2,109],51:[2,109],54:[2,109],63:[2,109],64:[2,109],65:[2,109],67:[2,109],69:[2,109],70:[2,109],71:[2,109],75:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],113:[2,109],114:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109]},{6:[2,49],25:[2,49],50:222,51:[1,223],88:[2,49]},{6:[2,117],25:[2,117],26:[2,117],51:[2,117],83:[2,117],88:[2,117]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:224,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,123],25:[2,123],26:[2,123],51:[2,123],83:[2,123],88:[2,123]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],37:[2,108],40:[2,108],46:[2,108],51:[2,108],54:[2,108],63:[2,108],64:[2,108],65:[2,108],67:[2,108],69:[2,108],70:[2,108],71:[2,108],75:[2,108],77:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],127:[2,108],128:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108],135:[2,108]},{5:225,25:[1,5],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],46:[2,134],51:[2,134],54:[2,134],69:[2,134],75:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],100:84,101:[1,62],102:[1,226],103:[1,63],106:85,107:[1,65],108:66,115:[2,134],123:[2,134],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],46:[2,136],51:[2,136],54:[2,136],69:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:84,101:[1,62],102:[1,227],103:[1,63],106:85,107:[1,65],108:66,115:[2,136],123:[2,136],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],46:[2,142],51:[2,142],54:[2,142],69:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],46:[2,143],51:[2,143],54:[2,143],69:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],100:84,101:[1,62],102:[2,143],103:[1,63],106:85,107:[1,65],108:66,115:[2,143],123:[2,143],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],46:[2,147],51:[2,147],54:[2,147],69:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{113:[2,149],114:[2,149]},{27:156,28:[1,70],55:157,56:158,73:[1,67],87:[1,112],110:228,112:155},{51:[1,229],113:[2,154],114:[2,154]},{51:[2,151],113:[2,151],114:[2,151]},{51:[2,152],113:[2,152],114:[2,152]},{51:[2,153],113:[2,153],114:[2,153]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],46:[2,148],51:[2,148],54:[2,148],69:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{8:230,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:231,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,49],25:[2,49],50:232,51:[1,233],75:[2,49]},{6:[2,86],25:[2,86],26:[2,86],51:[2,86],75:[2,86]},{6:[2,35],25:[2,35],26:[2,35],40:[1,234],51:[2,35],75:[2,35]},{6:[2,38],25:[2,38],26:[2,38],51:[2,38],75:[2,38]},{6:[2,39],25:[2,39],26:[2,39],40:[2,39],51:[2,39],75:[2,39]},{6:[2,40],25:[2,40],26:[2,40],40:[2,40],51:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],40:[2,41],51:[2,41],75:[2,41]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],46:[2,25],51:[2,25],54:[2,25],69:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],46:[2,185],51:[2,185],54:[2,185],69:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],100:84,101:[2,185],102:[2,185],103:[2,185],106:85,107:[2,185],108:66,115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[1,75],130:[1,78],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],46:[2,186],51:[2,186],54:[2,186],69:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],100:84,101:[2,186],102:[2,186],103:[2,186],106:85,107:[2,186],108:66,115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[1,75],130:[1,78],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],46:[2,187],51:[2,187],54:[2,187],69:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:84,101:[2,187],102:[2,187],103:[2,187],106:85,107:[2,187],108:66,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,75],130:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],46:[2,188],51:[2,188],54:[2,188],69:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:84,101:[2,188],102:[2,188],103:[2,188],106:85,107:[2,188],108:66,115:[2,188],123:[2,188],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],46:[2,189],51:[2,189],54:[2,189],69:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:84,101:[2,189],102:[2,189],103:[2,189],106:85,107:[2,189],108:66,115:[2,189],123:[2,189],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[2,189],133:[2,189],134:[1,82]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],46:[2,190],51:[2,190],54:[2,190],69:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:84,101:[2,190],102:[2,190],103:[2,190],106:85,107:[2,190],108:66,115:[2,190],123:[2,190],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[2,190],134:[1,82]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],46:[2,191],51:[2,191],54:[2,191],69:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:84,101:[2,191],102:[2,191],103:[2,191],106:85,107:[2,191],108:66,115:[2,191],123:[2,191],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[2,191],133:[2,191],134:[2,191]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],46:[2,176],51:[2,176],54:[2,176],69:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],100:84,101:[1,62],102:[2,176],103:[1,63],106:85,107:[1,65],108:66,115:[2,176],123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],46:[2,175],51:[2,175],54:[2,175],69:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],100:84,101:[1,62],102:[2,175],103:[1,63],106:85,107:[1,65],108:66,115:[2,175],123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],46:[2,98],51:[2,98],54:[2,98],63:[2,98],64:[2,98],65:[2,98],67:[2,98],69:[2,98],70:[2,98],71:[2,98],75:[2,98],81:[2,98],82:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],37:[2,74],46:[2,74],51:[2,74],54:[2,74],63:[2,74],64:[2,74],65:[2,74],67:[2,74],69:[2,74],70:[2,74],71:[2,74],75:[2,74],77:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],127:[2,74],128:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],37:[2,75],46:[2,75],51:[2,75],54:[2,75],63:[2,75],64:[2,75],65:[2,75],67:[2,75],69:[2,75],70:[2,75],71:[2,75],75:[2,75],77:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],127:[2,75],128:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],37:[2,76],46:[2,76],51:[2,76],54:[2,76],63:[2,76],64:[2,76],65:[2,76],67:[2,76],69:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{69:[1,235]},{54:[1,189],69:[2,82],89:236,90:[1,188],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{69:[2,83]},{8:237,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:[2,111],28:[2,111],30:[2,111],31:[2,111],33:[2,111],34:[2,111],35:[2,111],42:[2,111],43:[2,111],44:[2,111],48:[2,111],49:[2,111],69:[2,111],73:[2,111],76:[2,111],80:[2,111],85:[2,111],86:[2,111],87:[2,111],93:[2,111],97:[2,111],98:[2,111],101:[2,111],103:[2,111],105:[2,111],107:[2,111],116:[2,111],122:[2,111],124:[2,111],125:[2,111],126:[2,111],127:[2,111],128:[2,111]},{13:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],42:[2,112],43:[2,112],44:[2,112],48:[2,112],49:[2,112],69:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],37:[2,80],46:[2,80],51:[2,80],54:[2,80],63:[2,80],64:[2,80],65:[2,80],67:[2,80],69:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],37:[2,81],46:[2,81],51:[2,81],54:[2,81],63:[2,81],64:[2,81],65:[2,81],67:[2,81],69:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],46:[2,99],51:[2,99],54:[2,99],63:[2,99],64:[2,99],65:[2,99],67:[2,99],69:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],46:[2,33],51:[2,33],54:[2,33],69:[2,33],75:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],100:84,101:[2,33],102:[2,33],103:[2,33],106:85,107:[2,33],108:66,115:[2,33],123:[2,33],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:238,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],46:[2,104],51:[2,104],54:[2,104],63:[2,104],64:[2,104],65:[2,104],67:[2,104],69:[2,104],70:[2,104],71:[2,104],75:[2,104],81:[2,104],82:[2,104],83:[2,104],88:[2,104],90:[2,104],99:[2,104],101:[2,104],102:[2,104],103:[2,104],107:[2,104],115:[2,104],123:[2,104],125:[2,104],126:[2,104],129:[2,104],130:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104]},{6:[2,49],25:[2,49],50:239,51:[1,223],83:[2,49]},{6:[2,122],25:[2,122],26:[2,122],51:[2,122],54:[1,240],83:[2,122],88:[2,122],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{47:241,48:[1,57],49:[1,58]},{27:107,28:[1,70],41:108,52:242,53:106,55:109,56:110,73:[1,67],86:[1,111],87:[1,112]},{46:[2,55],51:[2,55]},{8:243,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],46:[2,192],51:[2,192],54:[2,192],69:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:84,101:[2,192],102:[2,192],103:[2,192],106:85,107:[2,192],108:66,115:[2,192],123:[2,192],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:244,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],46:[2,194],51:[2,194],54:[2,194],69:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],100:84,101:[2,194],102:[2,194],103:[2,194],106:85,107:[2,194],108:66,115:[2,194],123:[2,194],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],46:[2,174],51:[2,174],54:[2,174],69:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{8:245,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,127],6:[2,127],25:[2,127],26:[2,127],46:[2,127],51:[2,127],54:[2,127],69:[2,127],75:[2,127],83:[2,127],88:[2,127],90:[2,127],95:[1,246],99:[2,127],101:[2,127],102:[2,127],103:[2,127],107:[2,127],115:[2,127],123:[2,127],125:[2,127],126:[2,127],129:[2,127],130:[2,127],131:[2,127],132:[2,127],133:[2,127],134:[2,127]},{5:247,25:[1,5]},{27:248,28:[1,70]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,167],118:[2,167],120:[2,167]},{8:254,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],92:253,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,92],5:255,6:[2,92],25:[1,5],26:[2,92],46:[2,92],51:[2,92],54:[2,92],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,92],70:[1,97],71:[1,98],75:[2,92],78:89,81:[1,91],82:[2,102],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],46:[2,66],51:[2,66],54:[2,66],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,66],70:[2,66],71:[2,66],75:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66]},{1:[2,95],6:[2,95],25:[2,95],26:[2,95],46:[2,95],51:[2,95],54:[2,95],69:[2,95],75:[2,95],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{14:256,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:215,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],46:[2,132],51:[2,132],54:[2,132],63:[2,132],64:[2,132],65:[2,132],67:[2,132],69:[2,132],70:[2,132],71:[2,132],75:[2,132],81:[2,132],82:[2,132],83:[2,132],88:[2,132],90:[2,132],99:[2,132],101:[2,132],102:[2,132],103:[2,132],107:[2,132],115:[2,132],123:[2,132],125:[2,132],126:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132]},{6:[1,71],26:[1,257]},{8:258,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,61],13:[2,112],25:[2,61],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],42:[2,112],43:[2,112],44:[2,112],48:[2,112],49:[2,112],51:[2,61],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],88:[2,61],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,50],8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[2,50],26:[2,50],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],83:[2,50],85:[1,55],86:[1,56],87:[1,54],88:[2,50],91:262,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,49],25:[2,49],26:[2,49],50:263,51:[1,223]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],46:[2,171],51:[2,171],54:[2,171],69:[2,171],75:[2,171],83:[2,171],88:[2,171],90:[2,171],99:[2,171],101:[2,171],102:[2,171],103:[2,171],107:[2,171],115:[2,171],118:[2,171],123:[2,171],125:[2,171],126:[2,171],129:[2,171],130:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171]},{8:264,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,150],114:[2,150]},{27:156,28:[1,70],55:157,56:158,73:[1,67],87:[1,112],112:266},{1:[2,156],6:[2,156],25:[2,156],26:[2,156],46:[2,156],51:[2,156],54:[2,156],69:[2,156],75:[2,156],83:[2,156],88:[2,156],90:[2,156],99:[2,156],100:84,101:[2,156],102:[1,267],103:[2,156],106:85,107:[2,156],108:66,115:[1,268],123:[2,156],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,157],6:[2,157],25:[2,157],26:[2,157],46:[2,157],51:[2,157],54:[2,157],69:[2,157],75:[2,157],83:[2,157],88:[2,157],90:[2,157],99:[2,157],100:84,101:[2,157],102:[1,269],103:[2,157],106:85,107:[2,157],108:66,115:[2,157],123:[2,157],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,50],12:165,25:[2,50],26:[2,50],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:273,39:164,41:168,43:[1,46],75:[2,50],86:[1,111]},{8:274,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,275],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],37:[2,79],46:[2,79],51:[2,79],54:[2,79],63:[2,79],64:[2,79],65:[2,79],67:[2,79],69:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{8:276,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,69:[2,115],73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{69:[2,116],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,277],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,61],25:[2,61],26:[2,61],51:[2,61],83:[2,61],88:[2,61]},{5:279,25:[1,5]},{46:[2,53],51:[2,53]},{46:[2,56],51:[2,56],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,280],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{5:281,25:[1,5],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{5:282,25:[1,5]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],46:[2,128],51:[2,128],54:[2,128],69:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],46:[2,165],51:[2,165],54:[2,165],69:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{5:286,25:[1,5]},{26:[2,168],118:[2,168],120:[2,168]},{5:287,25:[1,5],51:[1,288]},{25:[2,124],51:[2,124],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,93],6:[2,93],25:[2,93],26:[2,93],46:[2,93],51:[2,93],54:[2,93],69:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],101:[2,93],102:[2,93],103:[2,93],107:[2,93],115:[2,93],123:[2,93],125:[2,93],126:[2,93],129:[2,93],130:[2,93],131:[2,93],132:[2,93],133:[2,93],134:[2,93]},{1:[2,96],5:289,6:[2,96],25:[1,5],26:[2,96],46:[2,96],51:[2,96],54:[2,96],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,96],70:[1,97],71:[1,98],75:[2,96],78:89,81:[1,91],82:[2,102],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{99:[1,290]},{88:[1,291],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],37:[2,110],46:[2,110],51:[2,110],54:[2,110],63:[2,110],64:[2,110],65:[2,110],67:[2,110],69:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],91:292,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:293,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,118],25:[2,118],26:[2,118],51:[2,118],83:[2,118],88:[2,118]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],46:[2,135],51:[2,135],54:[2,135],69:[2,135],75:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],100:84,101:[1,62],102:[2,135],103:[1,63],106:85,107:[1,65],108:66,115:[2,135],123:[2,135],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],46:[2,137],51:[2,137],54:[2,137],69:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:84,101:[1,62],102:[2,137],103:[1,63],106:85,107:[1,65],108:66,115:[2,137],123:[2,137],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{113:[2,155],114:[2,155]},{8:295,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],37:[2,84],46:[2,84],51:[2,84],54:[2,84],63:[2,84],64:[2,84],65:[2,84],67:[2,84],69:[2,84],70:[2,84],71:[2,84],75:[2,84],81:[2,84],82:[2,84],83:[2,84],88:[2,84],90:[2,84],99:[2,84],101:[2,84],102:[2,84],103:[2,84],107:[2,84],113:[2,84],114:[2,84],115:[2,84],123:[2,84],125:[2,84],126:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84]},{12:165,27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:298,39:164,41:168,43:[1,46],86:[1,111]},{6:[2,85],12:165,25:[2,85],26:[2,85],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:163,39:164,41:168,43:[1,46],51:[2,85],74:299,86:[1,111]},{6:[2,87],25:[2,87],26:[2,87],51:[2,87],75:[2,87]},{6:[2,36],25:[2,36],26:[2,36],51:[2,36],75:[2,36],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:300,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{69:[2,114],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],46:[2,34],51:[2,34],54:[2,34],69:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],101:[2,34],102:[2,34],103:[2,34],107:[2,34],115:[2,34],123:[2,34],125:[2,34],126:[2,34],129:[2,34],130:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],46:[2,105],51:[2,105],54:[2,105],63:[2,105],64:[2,105],65:[2,105],67:[2,105],69:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{1:[2,45],6:[2,45],25:[2,45],26:[2,45],46:[2,45],51:[2,45],54:[2,45],69:[2,45],75:[2,45],83:[2,45],88:[2,45],90:[2,45],99:[2,45],101:[2,45],102:[2,45],103:[2,45],107:[2,45],115:[2,45],123:[2,45],125:[2,45],126:[2,45],129:[2,45],130:[2,45],131:[2,45],132:[2,45],133:[2,45],134:[2,45]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],46:[2,193],51:[2,193],54:[2,193],69:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],101:[2,193],102:[2,193],103:[2,193],107:[2,193],115:[2,193],123:[2,193],125:[2,193],126:[2,193],129:[2,193],130:[2,193],131:[2,193],132:[2,193],133:[2,193],134:[2,193]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],46:[2,172],51:[2,172],54:[2,172],69:[2,172],75:[2,172],83:[2,172],88:[2,172],90:[2,172],99:[2,172],101:[2,172],102:[2,172],103:[2,172],107:[2,172],115:[2,172],118:[2,172],123:[2,172],125:[2,172],126:[2,172],129:[2,172],130:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],46:[2,129],51:[2,129],54:[2,129],69:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],46:[2,130],51:[2,130],54:[2,130],69:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],95:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],46:[2,163],51:[2,163],54:[2,163],69:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],101:[2,163],102:[2,163],103:[2,163],107:[2,163],115:[2,163],123:[2,163],125:[2,163],126:[2,163],129:[2,163],130:[2,163],131:[2,163],132:[2,163],133:[2,163],134:[2,163]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,169],118:[2,169],120:[2,169]},{8:304,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,97],6:[2,97],25:[2,97],26:[2,97],46:[2,97],51:[2,97],54:[2,97],69:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],101:[2,97],102:[2,97],103:[2,97],107:[2,97],115:[2,97],123:[2,97],125:[2,97],126:[2,97],129:[2,97],130:[2,97],131:[2,97],132:[2,97],133:[2,97],134:[2,97]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],46:[2,133],51:[2,133],54:[2,133],63:[2,133],64:[2,133],65:[2,133],67:[2,133],69:[2,133],70:[2,133],71:[2,133],75:[2,133],81:[2,133],82:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],101:[2,133],102:[2,133],103:[2,133],107:[2,133],115:[2,133],123:[2,133],125:[2,133],126:[2,133],129:[2,133],130:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],46:[2,113],51:[2,113],54:[2,113],63:[2,113],64:[2,113],65:[2,113],67:[2,113],69:[2,113],70:[2,113],71:[2,113],75:[2,113],81:[2,113],82:[2,113],83:[2,113],88:[2,113],90:[2,113],99:[2,113],101:[2,113],102:[2,113],103:[2,113],107:[2,113],115:[2,113],123:[2,113],125:[2,113],126:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113]},{6:[2,119],25:[2,119],26:[2,119],51:[2,119],83:[2,119],88:[2,119]},{6:[2,49],25:[2,49],26:[2,49],50:305,51:[1,223]},{6:[2,120],25:[2,120],26:[2,120],51:[2,120],83:[2,120],88:[2,120]},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],46:[2,158],51:[2,158],54:[2,158],69:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:84,101:[2,158],102:[2,158],103:[2,158],106:85,107:[2,158],108:66,115:[1,306],123:[2,158],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],46:[2,160],51:[2,160],54:[2,160],69:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:84,101:[2,160],102:[1,307],103:[2,160],106:85,107:[2,160],108:66,115:[2,160],123:[2,160],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],46:[2,159],51:[2,159],54:[2,159],69:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:84,101:[2,159],102:[2,159],103:[2,159],106:85,107:[2,159],108:66,115:[2,159],123:[2,159],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[2,88],25:[2,88],26:[2,88],51:[2,88],75:[2,88]},{6:[2,49],25:[2,49],26:[2,49],50:308,51:[1,233]},{26:[1,309],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,310]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],46:[2,166],51:[2,166],54:[2,166],69:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{26:[2,170],118:[2,170],120:[2,170]},{25:[2,125],51:[2,125],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,37],25:[2,37],26:[2,37],51:[2,37],75:[2,37]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],46:[2,164],51:[2,164],54:[2,164],69:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],101:[2,164],102:[2,164],103:[2,164],107:[2,164],115:[2,164],123:[2,164],125:[2,164],126:[2,164],129:[2,164],130:[2,164],131:[2,164],132:[2,164],133:[2,164],134:[2,164]},{6:[2,121],25:[2,121],26:[2,121],51:[2,121],83:[2,121],88:[2,121]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],46:[2,161],51:[2,161],54:[2,161],69:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:84,101:[2,161],102:[2,161],103:[2,161],106:85,107:[2,161],108:66,115:[2,161],123:[2,161],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],46:[2,162],51:[2,162],54:[2,162],69:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:84,101:[2,162],102:[2,162],103:[2,162],106:85,107:[2,162],108:66,115:[2,162],123:[2,162],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[2,89],25:[2,89],26:[2,89],51:[2,89],75:[2,89]}],
+defaultActions: {57:[2,47],58:[2,48],72:[2,3],91:[2,103],186:[2,83]},
+parseError: function parseError(str, hash) {
+    throw new Error(str);
+},
+parse: function parse(input) {
+    var self = this,
+        stack = [0],
+        vstack = [null], // semantic value stack
+        lstack = [], // location stack
+        table = this.table,
+        yytext = '',
+        yylineno = 0,
+        yyleng = 0,
+        recovering = 0,
+        TERROR = 2,
+        EOF = 1;
+
+    //this.reductionCount = this.shiftCount = 0;
+
+    this.lexer.setInput(input);
+    this.lexer.yy = this.yy;
+    this.yy.lexer = this.lexer;
+    if (typeof this.lexer.yylloc == 'undefined')
+        this.lexer.yylloc = {};
+    var yyloc = this.lexer.yylloc;
+    lstack.push(yyloc);
+
+    if (typeof this.yy.parseError === 'function')
+        this.parseError = this.yy.parseError;
+
+    function popStack (n) {
+        stack.length = stack.length - 2*n;
+        vstack.length = vstack.length - n;
+        lstack.length = lstack.length - n;
+    }
+
+    function lex() {
+        var token;
+        token = self.lexer.lex() || 1; // $end = 1
+        // if token isn't its numeric value, convert
+        if (typeof token !== 'number') {
+            token = self.symbols_[token] || token;
+        }
+        return token;
+    };
+
+    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
+    while (true) {
+        // retreive state number from top of stack
+        state = stack[stack.length-1];
+
+        // use default actions if available
+        if (this.defaultActions[state]) {
+            action = this.defaultActions[state];
+        } else {
+            if (symbol == null)
+                symbol = lex();
+            // read action for current state and first input
+            action = table[state] && table[state][symbol];
+        }
+
+        // handle parse error
+        if (typeof action === 'undefined' || !action.length || !action[0]) {
+
+            if (!recovering) {
+                // Report error
+                expected = [];
+                for (p in table[state]) if (this.terminals_[p] && p > 2) {
+                    expected.push("'"+this.terminals_[p]+"'");
+                }
+                var errStr = '';
+                if (this.lexer.showPosition) {
+                    errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', ');
+                } else {
+                    errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
+                                  (symbol == 1 /*EOF*/ ? "end of input" :
+                                              ("'"+(this.terminals_[symbol] || symbol)+"'"));
+                }
+                this.parseError(errStr,
+                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
+            }
+
+            // just recovered from another error
+            if (recovering == 3) {
+                if (symbol == EOF) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+
+                // discard current lookahead and grab another
+                yyleng = this.lexer.yyleng;
+                yytext = this.lexer.yytext;
+                yylineno = this.lexer.yylineno;
+                yyloc = this.lexer.yylloc;
+                symbol = lex();
+            }
+
+            // try to recover from error
+            while (1) {
+                // check for error recovery rule in this state
+                if ((TERROR.toString()) in table[state]) {
+                    break;
+                }
+                if (state == 0) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+                popStack(1);
+                state = stack[stack.length-1];
+            }
+
+            preErrorSymbol = symbol; // save the lookahead token
+            symbol = TERROR;         // insert generic error symbol as new lookahead
+            state = stack[stack.length-1];
+            action = table[state] && table[state][TERROR];
+            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
+        }
+
+        // this shouldn't happen, unless resolve defaults are off
+        if (action[0] instanceof Array && action.length > 1) {
+            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
+        }
+
+        switch (action[0]) {
+
+            case 1: // shift
+                //this.shiftCount++;
+
+                stack.push(symbol);
+                vstack.push(this.lexer.yytext);
+                lstack.push(this.lexer.yylloc);
+                stack.push(action[1]); // push state
+                symbol = null;
+                if (!preErrorSymbol) { // normal execution/no error
+                    yyleng = this.lexer.yyleng;
+                    yytext = this.lexer.yytext;
+                    yylineno = this.lexer.yylineno;
+                    yyloc = this.lexer.yylloc;
+                    if (recovering > 0)
+                        recovering--;
+                } else { // error just occurred, resume old lookahead f/ before error
+                    symbol = preErrorSymbol;
+                    preErrorSymbol = null;
+                }
+                break;
+
+            case 2: // reduce
+                //this.reductionCount++;
+
+                len = this.productions_[action[1]][1];
+
+                // perform semantic action
+                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
+                // default location, uses first token for firsts, last for lasts
+                yyval._$ = {
+                    first_line: lstack[lstack.length-(len||1)].first_line,
+                    last_line: lstack[lstack.length-1].last_line,
+                    first_column: lstack[lstack.length-(len||1)].first_column,
+                    last_column: lstack[lstack.length-1].last_column
+                };
+                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+
+                if (typeof r !== 'undefined') {
+                    return r;
+                }
+
+                // pop off stack
+                if (len) {
+                    stack = stack.slice(0,-1*len*2);
+                    vstack = vstack.slice(0, -1*len);
+                    lstack = lstack.slice(0, -1*len);
+                }
+
+                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)
+                vstack.push(yyval.$);
+                lstack.push(yyval._$);
+                // goto new state = table[STATE][NONTERMINAL]
+                newState = table[stack[stack.length-2]][stack[stack.length-1]];
+                stack.push(newState);
+                break;
+
+            case 3: // accept
+                return true;
+        }
+
+    }
+
+    return true;
+}};
+return parser;
+})();
+if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
+exports.parser = parser;
+exports.parse = function () { return parser.parse.apply(parser, arguments); }
+exports.main = function commonjsMain(args) {
+    if (!args[1])
+        throw new Error('Usage: '+args[0]+' FILE');
+    if (typeof process !== 'undefined') {
+        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
+    } else {
+        var cwd = require("file").path(require("file").cwd());
+        var source = cwd.join(args[1]).read({charset: "utf-8"});
+    }
+    return exports.parser.parse(source);
+}
+if (typeof module !== 'undefined' && require.main === module) {
+  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
+}
+}
\ No newline at end of file
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/repl.js b/weinre.build/vendor/node_modules/coffee-script/lib/repl.js
new file mode 100644
index 0000000..9e1bf7c
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/repl.js
@@ -0,0 +1,123 @@
+(function() {
+  var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, g, getCompletions, inspect, nonContextGlobals, readline, repl, run, sandbox, stdin, stdout, _i, _len;
+  CoffeeScript = require('./coffee-script');
+  readline = require('readline');
+  inspect = require('util').inspect;
+  Script = require('vm').Script;
+  Module = require('module');
+  REPL_PROMPT = 'coffee> ';
+  REPL_PROMPT_CONTINUATION = '......> ';
+  enableColours = false;
+  if (process.platform !== 'win32') {
+    enableColours = !process.env.NODE_DISABLE_COLORS;
+  }
+  stdin = process.openStdin();
+  stdout = process.stdout;
+  error = function(err) {
+    return stdout.write((err.stack || err.toString()) + '\n\n');
+  };
+  backlog = '';
+  sandbox = Script.createContext();
+  nonContextGlobals = ['Buffer', 'console', 'process', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'];
+  for (_i = 0, _len = nonContextGlobals.length; _i < _len; _i++) {
+    g = nonContextGlobals[_i];
+    sandbox[g] = global[g];
+  }
+  sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
+  run = function(buffer) {
+    var code, returnValue, _;
+    if (!buffer.toString().trim() && !backlog) {
+      repl.prompt();
+      return;
+    }
+    code = backlog += buffer;
+    if (code[code.length - 1] === '\\') {
+      backlog = "" + backlog.slice(0, -1) + "\n";
+      repl.setPrompt(REPL_PROMPT_CONTINUATION);
+      repl.prompt();
+      return;
+    }
+    repl.setPrompt(REPL_PROMPT);
+    backlog = '';
+    try {
+      _ = sandbox._;
+      returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
+        sandbox: sandbox,
+        filename: 'repl',
+        modulename: 'repl'
+      });
+      if (returnValue === void 0) {
+        sandbox._ = _;
+      } else {
+        process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
+      }
+    } catch (err) {
+      error(err);
+    }
+    return repl.prompt();
+  };
+  ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
+  SIMPLEVAR = /\s*(\w*)$/i;
+  autocomplete = function(text) {
+    return completeAttribute(text) || completeVariable(text) || [[], text];
+  };
+  completeAttribute = function(text) {
+    var all, completions, match, obj, prefix, val;
+    if (match = text.match(ACCESSOR)) {
+      all = match[0], obj = match[1], prefix = match[2];
+      try {
+        val = Script.runInContext(obj, sandbox);
+      } catch (error) {
+        return;
+      }
+      completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
+      return [completions, prefix];
+    }
+  };
+  completeVariable = function(text) {
+    var completions, free, possibilities, vars, _ref;
+    if (free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0) {
+      vars = Script.runInContext('Object.getOwnPropertyNames(this)', sandbox);
+      possibilities = vars.concat(CoffeeScript.RESERVED);
+      completions = getCompletions(free, possibilities);
+      return [completions, free];
+    }
+  };
+  getCompletions = function(prefix, candidates) {
+    var el, _j, _len2, _results;
+    _results = [];
+    for (_j = 0, _len2 = candidates.length; _j < _len2; _j++) {
+      el = candidates[_j];
+      if (el.indexOf(prefix) === 0) {
+        _results.push(el);
+      }
+    }
+    return _results;
+  };
+  process.on('uncaughtException', error);
+  if (readline.createInterface.length < 3) {
+    repl = readline.createInterface(stdin, autocomplete);
+    stdin.on('data', function(buffer) {
+      return repl.write(buffer);
+    });
+  } else {
+    repl = readline.createInterface(stdin, stdout, autocomplete);
+  }
+  repl.on('attemptClose', function() {
+    if (backlog) {
+      backlog = '';
+      process.stdout.write('\n');
+      repl.setPrompt(REPL_PROMPT);
+      return repl.prompt();
+    } else {
+      return repl.close();
+    }
+  });
+  repl.on('close', function() {
+    process.stdout.write('\n');
+    return stdin.destroy();
+  });
+  repl.on('line', run);
+  repl.setPrompt(REPL_PROMPT);
+  repl.prompt();
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/rewriter.js b/weinre.build/vendor/node_modules/coffee-script/lib/rewriter.js
new file mode 100644
index 0000000..d50a222
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/rewriter.js
@@ -0,0 +1,363 @@
+(function() {
+  var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
+  var __indexOf = Array.prototype.indexOf || function(item) {
+    for (var i = 0, l = this.length; i < l; i++) {
+      if (this[i] === item) return i;
+    }
+    return -1;
+  }, __slice = Array.prototype.slice;
+  exports.Rewriter = (function() {
+    function Rewriter() {}
+    Rewriter.prototype.rewrite = function(tokens) {
+      this.tokens = tokens;
+      this.removeLeadingNewlines();
+      this.removeMidExpressionNewlines();
+      this.closeOpenCalls();
+      this.closeOpenIndexes();
+      this.addImplicitIndentation();
+      this.tagPostfixConditionals();
+      this.addImplicitBraces();
+      this.addImplicitParentheses();
+      this.ensureBalance(BALANCED_PAIRS);
+      this.rewriteClosingParens();
+      return this.tokens;
+    };
+    Rewriter.prototype.scanTokens = function(block) {
+      var i, token, tokens;
+      tokens = this.tokens;
+      i = 0;
+      while (token = tokens[i]) {
+        i += block.call(this, token, i, tokens);
+      }
+      return true;
+    };
+    Rewriter.prototype.detectEnd = function(i, condition, action) {
+      var levels, token, tokens, _ref, _ref2;
+      tokens = this.tokens;
+      levels = 0;
+      while (token = tokens[i]) {
+        if (levels === 0 && condition.call(this, token, i)) {
+          return action.call(this, token, i);
+        }
+        if (!token || levels < 0) {
+          return action.call(this, token, i - 1);
+        }
+        if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
+          levels += 1;
+        } else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
+          levels -= 1;
+        }
+        i += 1;
+      }
+      return i - 1;
+    };
+    Rewriter.prototype.removeLeadingNewlines = function() {
+      var i, tag, _len, _ref;
+      _ref = this.tokens;
+      for (i = 0, _len = _ref.length; i < _len; i++) {
+        tag = _ref[i][0];
+        if (tag !== 'TERMINATOR') {
+          break;
+        }
+      }
+      if (i) {
+        return this.tokens.splice(0, i);
+      }
+    };
+    Rewriter.prototype.removeMidExpressionNewlines = function() {
+      return this.scanTokens(function(token, i, tokens) {
+        var _ref;
+        if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
+          return 1;
+        }
+        tokens.splice(i, 1);
+        return 0;
+      });
+    };
+    Rewriter.prototype.closeOpenCalls = function() {
+      var action, condition;
+      condition = function(token, i) {
+        var _ref;
+        return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
+      };
+      action = function(token, i) {
+        return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] === 'CALL_START') {
+          this.detectEnd(i + 1, condition, action);
+        }
+        return 1;
+      });
+    };
+    Rewriter.prototype.closeOpenIndexes = function() {
+      var action, condition;
+      condition = function(token, i) {
+        var _ref;
+        return (_ref = token[0]) === ']' || _ref === 'INDEX_END';
+      };
+      action = function(token, i) {
+        return token[0] = 'INDEX_END';
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] === 'INDEX_START') {
+          this.detectEnd(i + 1, condition, action);
+        }
+        return 1;
+      });
+    };
+    Rewriter.prototype.addImplicitBraces = function() {
+      var action, condition, stack, start, startIndent;
+      stack = [];
+      start = null;
+      startIndent = 0;
+      condition = function(token, i) {
+        var one, tag, three, two, _ref, _ref2;
+        _ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
+        if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
+          return false;
+        }
+        tag = token[0];
+        return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
+      };
+      action = function(token, i) {
+        var tok;
+        tok = ['}', '}', token[2]];
+        tok.generated = true;
+        return this.tokens.splice(i, 0, tok);
+      };
+      return this.scanTokens(function(token, i, tokens) {
+        var ago, idx, tag, tok, value, _ref, _ref2;
+        if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
+          stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
+          return 1;
+        }
+        if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
+          start = stack.pop();
+          return 1;
+        }
+        if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
+          return 1;
+        }
+        stack.push(['{']);
+        idx = ago === '@' ? i - 2 : i - 1;
+        while (this.tag(idx - 2) === 'HERECOMMENT') {
+          idx -= 2;
+        }
+        value = new String('{');
+        value.generated = true;
+        tok = ['{', value, token[2]];
+        tok.generated = true;
+        tokens.splice(idx, 0, tok);
+        this.detectEnd(i + 2, condition, action);
+        return 2;
+      });
+    };
+    Rewriter.prototype.addImplicitParentheses = function() {
+      var action, noCall;
+      noCall = false;
+      action = function(token, i) {
+        var idx;
+        idx = token[0] === 'OUTDENT' ? i + 1 : i;
+        return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
+      };
+      return this.scanTokens(function(token, i, tokens) {
+        var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
+        tag = token[0];
+        if (tag === 'CLASS' || tag === 'IF') {
+          noCall = true;
+        }
+        _ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
+        callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
+        seenSingle = false;
+        seenControl = false;
+        if (__indexOf.call(LINEBREAKS, tag) >= 0) {
+          noCall = false;
+        }
+        if (prev && !prev.spaced && tag === '?') {
+          token.call = true;
+        }
+        if (token.fromThen) {
+          return 1;
+        }
+        if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
+          return 1;
+        }
+        tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
+        this.detectEnd(i + 1, function(token, i) {
+          var post, _ref4;
+          tag = token[0];
+          if (!seenSingle && token.fromThen) {
+            return true;
+          }
+          if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
+            seenSingle = true;
+          }
+          if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
+            seenControl = true;
+          }
+          if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
+            return true;
+          }
+          return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
+        }, action);
+        if (prev[0] === '?') {
+          prev[0] = 'FUNC_EXIST';
+        }
+        return 2;
+      });
+    };
+    Rewriter.prototype.addImplicitIndentation = function() {
+      return this.scanTokens(function(token, i, tokens) {
+        var action, condition, indent, outdent, starter, tag, _ref, _ref2;
+        tag = token[0];
+        if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
+          tokens.splice(i, 1);
+          return 0;
+        }
+        if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
+          tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));
+          return 2;
+        }
+        if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
+          tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));
+          return 4;
+        }
+        if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
+          starter = tag;
+          _ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
+          if (starter === 'THEN') {
+            indent.fromThen = true;
+          }
+          indent.generated = outdent.generated = true;
+          tokens.splice(i + 1, 0, indent);
+          condition = function(token, i) {
+            var _ref3;
+            return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
+          };
+          action = function(token, i) {
+            return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
+          };
+          this.detectEnd(i + 2, condition, action);
+          if (tag === 'THEN') {
+            tokens.splice(i, 1);
+          }
+          return 1;
+        }
+        return 1;
+      });
+    };
+    Rewriter.prototype.tagPostfixConditionals = function() {
+      var condition;
+      condition = function(token, i) {
+        var _ref;
+        return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
+      };
+      return this.scanTokens(function(token, i) {
+        var original;
+        if (token[0] !== 'IF') {
+          return 1;
+        }
+        original = token;
+        this.detectEnd(i + 1, condition, function(token, i) {
+          if (token[0] !== 'INDENT') {
+            return original[0] = 'POST_' + original[0];
+          }
+        });
+        return 1;
+      });
+    };
+    Rewriter.prototype.ensureBalance = function(pairs) {
+      var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
+      levels = {};
+      openLine = {};
+      _ref = this.tokens;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        token = _ref[_i];
+        tag = token[0];
+        for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
+          _ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
+          levels[open] |= 0;
+          if (tag === open) {
+            if (levels[open]++ === 0) {
+              openLine[open] = token[2];
+            }
+          } else if (tag === close && --levels[open] < 0) {
+            throw Error("too many " + token[1] + " on line " + (token[2] + 1));
+          }
+        }
+      }
+      for (open in levels) {
+        level = levels[open];
+        if (level > 0) {
+          throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
+        }
+      }
+      return this;
+    };
+    Rewriter.prototype.rewriteClosingParens = function() {
+      var debt, key, stack;
+      stack = [];
+      debt = {};
+      for (key in INVERSES) {
+        debt[key] = 0;
+      }
+      return this.scanTokens(function(token, i, tokens) {
+        var inv, match, mtag, oppos, tag, val, _ref;
+        if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
+          stack.push(token);
+          return 1;
+        }
+        if (__indexOf.call(EXPRESSION_END, tag) < 0) {
+          return 1;
+        }
+        if (debt[inv = INVERSES[tag]] > 0) {
+          debt[inv] -= 1;
+          tokens.splice(i, 1);
+          return 0;
+        }
+        match = stack.pop();
+        mtag = match[0];
+        oppos = INVERSES[mtag];
+        if (tag === oppos) {
+          return 1;
+        }
+        debt[mtag] += 1;
+        val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
+        if (this.tag(i + 2) === mtag) {
+          tokens.splice(i + 3, 0, val);
+          stack.push(match);
+        } else {
+          tokens.splice(i, 0, val);
+        }
+        return 1;
+      });
+    };
+    Rewriter.prototype.indentation = function(token) {
+      return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
+    };
+    Rewriter.prototype.tag = function(i) {
+      var _ref;
+      return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
+    };
+    return Rewriter;
+  })();
+  BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
+  INVERSES = {};
+  EXPRESSION_START = [];
+  EXPRESSION_END = [];
+  for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
+    _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
+    EXPRESSION_START.push(INVERSES[rite] = left);
+    EXPRESSION_END.push(INVERSES[left] = rite);
+  }
+  EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
+  IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
+  IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
+  IMPLICIT_UNSPACED_CALL = ['+', '-'];
+  IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
+  IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
+  SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
+  SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
+  LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/lib/scope.js b/weinre.build/vendor/node_modules/coffee-script/lib/scope.js
new file mode 100644
index 0000000..ab88ba9
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/lib/scope.js
@@ -0,0 +1,120 @@
+(function() {
+  var Scope, extend, last, _ref;
+  _ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
+  exports.Scope = Scope = (function() {
+    Scope.root = null;
+    function Scope(parent, expressions, method) {
+      this.parent = parent;
+      this.expressions = expressions;
+      this.method = method;
+      this.variables = [
+        {
+          name: 'arguments',
+          type: 'arguments'
+        }
+      ];
+      this.positions = {};
+      if (!this.parent) {
+        Scope.root = this;
+      }
+    }
+    Scope.prototype.add = function(name, type, immediate) {
+      var pos;
+      if (this.shared && !immediate) {
+        return this.parent.add(name, type, immediate);
+      }
+      if (typeof (pos = this.positions[name]) === 'number') {
+        return this.variables[pos].type = type;
+      } else {
+        return this.positions[name] = this.variables.push({
+          name: name,
+          type: type
+        }) - 1;
+      }
+    };
+    Scope.prototype.find = function(name, options) {
+      if (this.check(name, options)) {
+        return true;
+      }
+      this.add(name, 'var');
+      return false;
+    };
+    Scope.prototype.parameter = function(name) {
+      if (this.shared && this.parent.check(name, true)) {
+        return;
+      }
+      return this.add(name, 'param');
+    };
+    Scope.prototype.check = function(name, immediate) {
+      var found, _ref2;
+      found = !!this.type(name);
+      if (found || immediate) {
+        return found;
+      }
+      return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
+    };
+    Scope.prototype.temporary = function(name, index) {
+      if (name.length > 1) {
+        return '_' + name + (index > 1 ? index : '');
+      } else {
+        return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
+      }
+    };
+    Scope.prototype.type = function(name) {
+      var v, _i, _len, _ref2;
+      _ref2 = this.variables;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.name === name) {
+          return v.type;
+        }
+      }
+      return null;
+    };
+    Scope.prototype.freeVariable = function(type) {
+      var index, temp;
+      index = 0;
+      while (this.check((temp = this.temporary(type, index)))) {
+        index++;
+      }
+      this.add(temp, 'var', true);
+      return temp;
+    };
+    Scope.prototype.assign = function(name, value) {
+      this.add(name, {
+        value: value,
+        assigned: true
+      });
+      return this.hasAssignments = true;
+    };
+    Scope.prototype.hasDeclarations = function() {
+      return !!this.declaredVariables().length;
+    };
+    Scope.prototype.declaredVariables = function() {
+      var realVars, tempVars, v, _i, _len, _ref2;
+      realVars = [];
+      tempVars = [];
+      _ref2 = this.variables;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.type === 'var') {
+          (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
+        }
+      }
+      return realVars.sort().concat(tempVars.sort());
+    };
+    Scope.prototype.assignedVariables = function() {
+      var v, _i, _len, _ref2, _results;
+      _ref2 = this.variables;
+      _results = [];
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.type.assigned) {
+          _results.push("" + v.name + " = " + v.type.value);
+        }
+      }
+      return _results;
+    };
+    return Scope;
+  })();
+}).call(this);
diff --git a/weinre.build/vendor/node_modules/coffee-script/package.json b/weinre.build/vendor/node_modules/coffee-script/package.json
new file mode 100644
index 0000000..58210ed
--- /dev/null
+++ b/weinre.build/vendor/node_modules/coffee-script/package.json
@@ -0,0 +1,27 @@
+{
+  "name":         "coffee-script",
+  "description":  "Unfancy JavaScript",
+  "keywords":     ["javascript", "language", "coffeescript", "compiler"],
+  "author":       "Jeremy Ashkenas",
+  "version":      "1.1.2",
+  "licenses":     [{
+    "type":       "MIT",
+    "url":        "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
+  }],
+  "engines":      {
+    "node":       ">=0.2.5"
+  },
+  "directories" : {
+    "lib" : "./lib"
+  },
+  "main" : "./lib/coffee-script",
+  "bin":          {
+    "coffee":     "./bin/coffee",
+    "cake":       "./bin/cake"
+  },
+  "homepage":     "http://coffeescript.org",
+  "repository":   {
+    "type": "git",
+    "url": "git://github.com/jashkenas/coffee-script.git"
+  }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/English.lproj/localizedStrings.js b/weinre.build/vendor/webkit/WebCore/English.lproj/localizedStrings.js
new file mode 100644
index 0000000..6f759a2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/English.lproj/localizedStrings.js
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptHost.idl b/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptHost.idl
new file mode 100644
index 0000000..5fb57b4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptHost.idl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+    interface [Conditional=INSPECTOR] InjectedScriptHost {
+        void clearConsoleMessages();
+
+        void copyText(in DOMString text);
+        [Custom] DOMObject nodeForId(in long nodeId);
+        [Custom] int pushNodePathToFrontend(in DOMObject node, in boolean withChildren, in boolean selectInUI);
+        long inspectedNode(in unsigned long num);
+        [Custom] DOMObject internalConstructorName(in DOMObject object);
+
+#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
+        [Custom] DOMObject currentCallFrame();
+#endif
+
+#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
+        [Custom] void selectDatabase(in DOMObject database);
+#endif
+
+#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE
+        [Custom] void selectDOMStorage(in DOMObject storage);
+#endif
+
+#if defined(ENABLE_WORKERS) && ENABLE_WORKERS
+        void didCreateWorker(in long id, in DOMString url, in boolean isFakeWorker);
+        void didDestroyWorker(in long id);
+        long nextWorkerId();
+#endif
+    };
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptSource.js b/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptSource.js
new file mode 100644
index 0000000..c88e8e4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/InjectedScriptSource.js
@@ -0,0 +1,763 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
+
+function bind(thisObject, memberFunction)
+{
+    var func = memberFunction;
+    var args = Array.prototype.slice.call(arguments, 2);
+    function bound()
+    {
+        return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0)));
+    }
+    bound.toString = function() {
+        return "bound: " + func;
+    };
+    return bound;
+}
+
+var InjectedScript = function()
+{
+    this._lastBoundObjectId = 1;
+    this._idToWrappedObject = {};
+    this._objectGroups = {};
+}
+
+InjectedScript.prototype = {
+    wrapObjectForConsole: function(object, canAccessInspectedWindow)
+    {
+        if (canAccessInspectedWindow)
+            return this._wrapObject(object, "console");
+        var result = {};
+        result.type = typeof object;
+        result.description = this._toString(object);
+        return result;
+    },
+
+    _wrapObject: function(object, objectGroupName, abbreviate)
+    {
+        try {
+            var objectId;
+            if (typeof object === "object" || typeof object === "function" || this._isHTMLAllCollection(object)) {
+                var id = this._lastBoundObjectId++;
+                this._idToWrappedObject[id] = object;
+    
+                var group = this._objectGroups[objectGroupName];
+                if (!group) {
+                    group = [];
+                    this._objectGroups[objectGroupName] = group;
+                }
+                group.push(id);
+                objectId = { injectedScriptId: injectedScriptId,
+                             id: id,
+                             groupName: objectGroupName };
+            }
+            return InjectedScript.RemoteObject.fromObject(object, objectId, abbreviate);
+        } catch (e) {
+            return InjectedScript.RemoteObject.fromObject("[ Exception: " + e.toString() + " ]");
+        }
+    },
+
+    _parseObjectId: function(objectId)
+    {
+        return eval("(" + objectId + ")");
+    },
+
+    releaseWrapperObjectGroup: function(objectGroupName)
+    {
+        var group = this._objectGroups[objectGroupName];
+        if (!group)
+            return;
+        for (var i = 0; i < group.length; i++)
+            delete this._idToWrappedObject[group[i]];
+        delete this._objectGroups[objectGroupName];
+    },
+
+    dispatch: function(methodName, args)
+    {
+        var argsArray = eval("(" + args + ")");
+        var result = this[methodName].apply(this, argsArray);
+        if (typeof result === "undefined") {
+            inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
+            result = null;
+        }
+        return result;
+    },
+
+    getProperties: function(objectId, ignoreHasOwnProperty, abbreviate)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+
+        if (!this._isDefined(object))
+            return false;
+        var properties = [];
+
+        var propertyNames = ignoreHasOwnProperty ? this._getPropertyNames(object) : Object.getOwnPropertyNames(object);
+        if (!ignoreHasOwnProperty && object.__proto__)
+            propertyNames.push("__proto__");
+    
+        // Go over properties, prepare results.
+        for (var i = 0; i < propertyNames.length; ++i) {
+            var propertyName = propertyNames[i];
+    
+            var property = {};
+            property.name = propertyName + "";
+            var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName);
+            if (!isGetter) {
+                try {
+                    property.value = this._wrapObject(object[propertyName], parsedObjectId.groupName, abbreviate);
+                } catch(e) {
+                    property.value = new InjectedScript.RemoteObject.fromException(e);
+                }
+            } else {
+                // FIXME: this should show something like "getter" (bug 16734).
+                property.value = new InjectedScript.RemoteObject.fromObject("\u2014"); // em dash
+                property.isGetter = true;
+            }
+            properties.push(property);
+        }
+        return properties;
+    },
+
+    setPropertyValue: function(objectId, propertyName, expression)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+        if (!this._isDefined(object))
+            return false;
+    
+        var expressionLength = expression.length;
+        if (!expressionLength) {
+            delete object[propertyName];
+            return !(propertyName in object);
+        }
+    
+        try {
+            // Surround the expression in parenthesis so the result of the eval is the result
+            // of the whole expression not the last potential sub-expression.
+    
+            // There is a regression introduced here: eval is now happening against global object,
+            // not call frame while on a breakpoint.
+            // TODO: bring evaluation against call frame back.
+            var result = inspectedWindow.eval("(" + expression + ")");
+            // Store the result in the property.
+            object[propertyName] = result;
+            return true;
+        } catch(e) {
+            try {
+                var result = inspectedWindow.eval("\"" + expression.replace(/"/g, "\\\"") + "\"");
+                object[propertyName] = result;
+                return true;
+            } catch(e) {
+                return false;
+            }
+        }
+    },
+
+    _populatePropertyNames: function(object, resultSet)
+    {
+        for (var o = object; o; o = o.__proto__) {
+            try {
+                var names = Object.getOwnPropertyNames(o);
+                for (var i = 0; i < names.length; ++i)
+                    resultSet[names[i]] = true;
+            } catch (e) {
+            }
+        }
+    },
+
+    _getPropertyNames: function(object, resultSet)
+    {
+        var propertyNameSet = {};
+        this._populatePropertyNames(object, propertyNameSet);
+        return Object.keys(propertyNameSet);
+    },
+
+    getCompletions: function(expression, includeCommandLineAPI)
+    {
+        var props = {};
+        try {
+            if (!expression)
+                expression = "this";
+            var expressionResult = this._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false, false);
+
+            if (typeof expressionResult === "object")
+                this._populatePropertyNames(expressionResult, props);
+
+            if (includeCommandLineAPI) {
+                for (var prop in CommandLineAPI.members_)
+                    props[CommandLineAPI.members_[prop]] = true;
+            }
+        } catch(e) {
+        }
+        return props;
+    },
+
+    getCompletionsOnCallFrame: function(callFrameId, expression, includeCommandLineAPI)
+    {
+        var props = {};
+        try {
+            var callFrame = this._callFrameForId(callFrameId);
+            if (!callFrame)
+                return props;
+
+            if (expression) {
+                var expressionResult = this._evaluateOn(callFrame.evaluate, callFrame, expression, true, false);
+                if (typeof expressionResult === "object")
+                    this._populatePropertyNames(expressionResult, props);
+            } else {
+                // Evaluate into properties in scope of the selected call frame.
+                var scopeChain = callFrame.scopeChain;
+                for (var i = 0; i < scopeChain.length; ++i)
+                    this._populatePropertyNames(scopeChain[i], props);
+            }
+    
+            if (includeCommandLineAPI) {
+                for (var prop in CommandLineAPI.members_)
+                    props[CommandLineAPI.members_[prop]] = true;
+            }
+        } catch(e) {
+        }
+        return props;
+    },
+
+    evaluate: function(expression, objectGroup, injectCommandLineAPI)
+    {
+        return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup, false, injectCommandLineAPI);
+    },
+
+    _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI)
+    {
+        try {
+            return this._wrapObject(this._evaluateOn(evalFunction, object, expression, isEvalOnCallFrame, injectCommandLineAPI), objectGroup);
+        } catch (e) {
+            return InjectedScript.RemoteObject.fromException(e);
+        }
+    },
+
+    _evaluateOn: function(evalFunction, object, expression, isEvalOnCallFrame, injectCommandLineAPI)
+    {
+        // Only install command line api object for the time of evaluation.
+        // Surround the expression in with statements to inject our command line API so that
+        // the window object properties still take more precedent than our API functions.
+
+        try {
+            if (injectCommandLineAPI && inspectedWindow.console) {
+                inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
+                expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
+            }
+
+            var value = evalFunction.call(object, expression);
+
+            // When evaluating on call frame error is not thrown, but returned as a value.
+            if (this._type(value) === "error")
+                throw value.toString();
+
+            return value;
+        } finally {
+            if (injectCommandLineAPI && inspectedWindow.console)
+                delete inspectedWindow.console._commandLineAPI;
+        }
+    },
+
+    getNodeId: function(node)
+    {
+        return InjectedScriptHost.pushNodePathToFrontend(node, false, false);
+    },
+
+    callFrames: function()
+    {
+        var callFrame = InjectedScriptHost.currentCallFrame();
+        if (!callFrame)
+            return false;
+    
+        injectedScript.releaseWrapperObjectGroup("backtrace");
+        var result = [];
+        var depth = 0;
+        do {
+            result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
+            callFrame = callFrame.caller;
+        } while (callFrame);
+        return result;
+    },
+
+    evaluateOnCallFrame: function(callFrameId, expression, objectGroup, injectCommandLineAPI)
+    {
+        var callFrame = this._callFrameForId(callFrameId);
+        if (!callFrame)
+            return false;
+        return this._evaluateAndWrap(callFrame.evaluate, callFrame, expression, objectGroup, true, injectCommandLineAPI);
+    },
+
+    _callFrameForId: function(callFrameId)
+    {
+        var parsedCallFrameId = eval("(" + callFrameId + ")");
+        var ordinal = parsedCallFrameId.ordinal;
+        var callFrame = InjectedScriptHost.currentCallFrame();
+        while (--ordinal >= 0 && callFrame)
+            callFrame = callFrame.caller;
+        return callFrame;
+    },
+
+    _nodeForId: function(nodeId)
+    {
+        if (!nodeId)
+            return null;
+        return InjectedScriptHost.nodeForId(nodeId);
+    },
+
+    _objectForId: function(objectId)
+    {
+        return this._idToWrappedObject[objectId.id];
+    },
+
+    resolveNode: function(nodeId)
+    {
+        var node = this._nodeForId(nodeId);
+        if (!node)
+            return false;
+        // FIXME: receive the object group from client.
+        return this._wrapObject(node, "prototype");
+    },
+
+    getNodeProperties: function(nodeId, properties)
+    {
+        var node = this._nodeForId(nodeId);
+        if (!node)
+            return false;
+        properties = eval("(" + properties + ")");
+        var result = {};
+        for (var i = 0; i < properties.length; ++i)
+            result[properties[i]] = node[properties[i]];
+        return result;
+    },
+
+    getNodePrototypes: function(nodeId)
+    {
+        this.releaseWrapperObjectGroup("prototypes");
+        var node = this._nodeForId(nodeId);
+        if (!node)
+            return false;
+
+        var result = [];
+        var prototype = node;
+        do {
+            result.push(this._wrapObject(prototype, "prototypes"));
+            prototype = prototype.__proto__;
+        } while (prototype)
+        return result;
+    },
+
+    pushNodeToFrontend: function(objectId)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+        if (!object || this._type(object) !== "node")
+            return false;
+        return InjectedScriptHost.pushNodePathToFrontend(object, false, false);
+    },
+
+    evaluateOnSelf: function(funcBody, args)
+    {
+        var func = eval("(" + funcBody + ")");
+        return func.apply(this, eval("(" + args + ")") || []);
+    },
+
+    _isDefined: function(object)
+    {
+        return object || this._isHTMLAllCollection(object);
+    },
+
+    _isHTMLAllCollection: function(object)
+    {
+        // document.all is reported as undefined, but we still want to process it.
+        return (typeof object === "undefined") && inspectedWindow.HTMLAllCollection && object instanceof inspectedWindow.HTMLAllCollection;
+    },
+
+    _type: function(obj)
+    {
+        if (obj === null)
+            return "null";
+
+        var type = typeof obj;
+        if (type !== "object" && type !== "function") {
+            // FIXME(33716): typeof document.all is always 'undefined'.
+            if (this._isHTMLAllCollection(obj))
+                return "array";
+            return type;
+        }
+
+        // If owning frame has navigated to somewhere else window properties will be undefined.
+        // In this case just return result of the typeof.
+        if (!inspectedWindow.document)
+            return type;
+
+        if (obj instanceof inspectedWindow.Node)
+            return (obj.nodeType === undefined ? type : "node");
+        if (obj instanceof inspectedWindow.String)
+            return "string";
+        if (obj instanceof inspectedWindow.Array)
+            return "array";
+        if (obj instanceof inspectedWindow.Boolean)
+            return "boolean";
+        if (obj instanceof inspectedWindow.Number)
+            return "number";
+        if (obj instanceof inspectedWindow.Date)
+            return "date";
+        if (obj instanceof inspectedWindow.RegExp)
+            return "regexp";
+        // FireBug's array detection.
+        if (isFinite(obj.length) && typeof obj.splice === "function")
+            return "array";
+        if (isFinite(obj.length) && typeof obj.callee === "function") // arguments.
+            return "array";
+        if (obj instanceof inspectedWindow.NodeList)
+            return "array";
+        if (obj instanceof inspectedWindow.HTMLCollection)
+            return "array";
+        if (obj instanceof inspectedWindow.Error)
+            return "error";
+        return type;
+    },
+
+    _describe: function(obj, abbreviated)
+    {
+        var type = this._type(obj);
+
+        switch (type) {
+        case "object":
+        case "node":
+            var result = InjectedScriptHost.internalConstructorName(obj);
+            if (result === "Object") {
+                // In Chromium DOM wrapper prototypes will have Object as their constructor name,
+                // get the real DOM wrapper name from the constructor property.
+                var constructorName = obj.constructor && obj.constructor.name;
+                if (constructorName)
+                    return constructorName;
+            }
+            return result;
+        case "array":
+            var className = InjectedScriptHost.internalConstructorName(obj);
+            if (typeof obj.length === "number")
+                className += "[" + obj.length + "]";
+            return className;
+        case "string":
+            if (!abbreviated)
+                return obj;
+            if (obj.length > 100)
+                return "\"" + obj.substring(0, 100) + "\u2026\"";
+            return "\"" + obj + "\"";
+        case "function":
+            var objectText = this._toString(obj);
+            if (abbreviated)
+                objectText = /.*/.exec(objectText)[0].replace(/ +$/g, "");
+            return objectText;
+        default:
+            return this._toString(obj);
+        }
+    },
+
+    _toString: function(obj)
+    {
+        // We don't use String(obj) because inspectedWindow.String is undefined if owning frame navigated to another page.
+        return "" + obj;
+    }
+}
+
+var injectedScript = new InjectedScript();
+
+InjectedScript.RemoteObject = function(objectId, type, description, hasChildren)
+{
+    this.objectId = objectId;
+    this.type = type;
+    this.description = description;
+    this.hasChildren = hasChildren;
+}
+
+InjectedScript.RemoteObject.fromException = function(e)
+{
+    return new InjectedScript.RemoteObject(null, "error", e.toString());
+}
+
+InjectedScript.RemoteObject.fromObject = function(object, objectId, abbreviate)
+{
+    var type = injectedScript._type(object);
+    var rawType = typeof object;
+    var hasChildren = (rawType === "object" && object !== null && (Object.getOwnPropertyNames(object).length || !!object.__proto__)) || rawType === "function";
+    var description = "";
+    try {
+        var description = injectedScript._describe(object, abbreviate);
+        return new InjectedScript.RemoteObject(objectId, type, description, hasChildren);
+    } catch (e) {
+        return InjectedScript.RemoteObject.fromException(e);
+    }
+}
+
+InjectedScript.CallFrameProxy = function(ordinal, callFrame)
+{
+    this.id = { ordinal: ordinal, injectedScriptId: injectedScriptId };
+    this.type = callFrame.type;
+    this.functionName = (this.type === "function" ? callFrame.functionName : "");
+    this.sourceID = callFrame.sourceID;
+    this.line = callFrame.line;
+    this.column = callFrame.column;
+    this.scopeChain = this._wrapScopeChain(callFrame);
+}
+
+InjectedScript.CallFrameProxy.prototype = {
+    _wrapScopeChain: function(callFrame)
+    {
+        const GLOBAL_SCOPE = 0;
+        const LOCAL_SCOPE = 1;
+        const WITH_SCOPE = 2;
+        const CLOSURE_SCOPE = 3;
+        const CATCH_SCOPE = 4;
+    
+        var scopeChain = callFrame.scopeChain;
+        var scopeChainProxy = [];
+        var foundLocalScope = false;
+        for (var i = 0; i < scopeChain.length; i++) {
+            var scopeType = callFrame.scopeType(i);
+            var scopeObject = scopeChain[i];
+            var scopeObjectProxy = injectedScript._wrapObject(scopeObject, "backtrace", true);
+
+            switch(scopeType) {
+                case LOCAL_SCOPE: {
+                    foundLocalScope = true;
+                    scopeObjectProxy.isLocal = true;
+                    scopeObjectProxy.thisObject = injectedScript._wrapObject(callFrame.thisObject, "backtrace", true);
+                    break;
+                }
+                case CLOSURE_SCOPE: {
+                    scopeObjectProxy.isClosure = true;
+                    break;
+                }
+                case WITH_SCOPE:
+                case CATCH_SCOPE: {
+                    if (foundLocalScope && scopeObject instanceof inspectedWindow.Element)
+                        scopeObjectProxy.isElement = true;
+                    else if (foundLocalScope && scopeObject instanceof inspectedWindow.Document)
+                        scopeObjectProxy.isDocument = true;
+                    else
+                        scopeObjectProxy.isWithBlock = true;
+                    break;
+                }
+            }
+            scopeChainProxy.push(scopeObjectProxy);
+        }
+        return scopeChainProxy;
+    }
+}
+
+function CommandLineAPI(commandLineAPIImpl, callFrame)
+{
+    function inScopeVariables(member)
+    {
+        if (!callFrame)
+            return false;
+
+        var scopeChain = callFrame.scopeChain;
+        for (var i = 0; i < scopeChain.length; ++i) {
+            if (member in scopeChain[i])
+                return true;
+        }
+        return false;
+    }
+
+    for (var i = 0; i < CommandLineAPI.members_.length; ++i) {
+        var member = CommandLineAPI.members_[i];
+        if (member in inspectedWindow || inScopeVariables(member))
+            continue;
+
+        this[member] = bind(commandLineAPIImpl, commandLineAPIImpl[member]);
+    }
+
+    for (var i = 0; i < 5; ++i) {
+        var member = "$" + i;
+        if (member in inspectedWindow || inScopeVariables(member))
+            continue;
+
+        this.__defineGetter__("$" + i, bind(commandLineAPIImpl, commandLineAPIImpl._inspectedNode, i));
+    }
+}
+
+CommandLineAPI.members_ = [
+    "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd",
+    "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear"
+];
+
+function CommandLineAPIImpl()
+{
+}
+
+CommandLineAPIImpl.prototype = {
+    $: function()
+    {
+        return document.getElementById.apply(document, arguments)
+    },
+
+    $$: function()
+    {
+        return document.querySelectorAll.apply(document, arguments)
+    },
+
+    $x: function(xpath, context)
+    {
+        var nodes = [];
+        try {
+            var doc = (context && context.ownerDocument) || inspectedWindow.document;
+            var results = doc.evaluate(xpath, context || doc, null, XPathResult.ANY_TYPE, null);
+            var node;
+            while (node = results.iterateNext())
+                nodes.push(node);
+        } catch (e) {
+        }
+        return nodes;
+    },
+
+    dir: function()
+    {
+        return console.dir.apply(console, arguments)
+    },
+
+    dirxml: function()
+    {
+        return console.dirxml.apply(console, arguments)
+    },
+
+    keys: function(object)
+    {
+        return Object.keys(object);
+    },
+
+    values: function(object)
+    {
+        var result = [];
+        for (var key in object)
+            result.push(object[key]);
+        return result;
+    },
+
+    profile: function()
+    {
+        return console.profile.apply(console, arguments)
+    },
+
+    profileEnd: function()
+    {
+        return console.profileEnd.apply(console, arguments)
+    },
+
+    monitorEvents: function(object, types)
+    {
+        if (!object || !object.addEventListener || !object.removeEventListener)
+            return;
+        types = this._normalizeEventTypes(types);
+        for (var i = 0; i < types.length; ++i) {
+            object.removeEventListener(types[i], this._logEvent, false);
+            object.addEventListener(types[i], this._logEvent, false);
+        }
+    },
+
+    unmonitorEvents: function(object, types)
+    {
+        if (!object || !object.addEventListener || !object.removeEventListener)
+            return;
+        types = this._normalizeEventTypes(types);
+        for (var i = 0; i < types.length; ++i)
+            object.removeEventListener(types[i], this._logEvent, false);
+    },
+
+    inspect: function(object)
+    {
+        if (arguments.length === 0)
+            return;
+
+        inspectedWindow.console.log(object);
+        if (injectedScript._type(object) === "node")
+            InjectedScriptHost.pushNodePathToFrontend(object, false, true);
+        else {
+            switch (injectedScript._describe(object)) {
+                case "Database":
+                    InjectedScriptHost.selectDatabase(object);
+                    break;
+                case "Storage":
+                    InjectedScriptHost.selectDOMStorage(object);
+                    break;
+            }
+        }
+    },
+
+    copy: function(object)
+    {
+        if (injectedScript._type(object) === "node")
+            object = object.outerHTML;
+        InjectedScriptHost.copyText(object);
+    },
+
+    clear: function()
+    {
+        InjectedScriptHost.clearConsoleMessages();
+    },
+
+    _inspectedNode: function(num)
+    {
+        var nodeId = InjectedScriptHost.inspectedNode(num);
+        return injectedScript._nodeForId(nodeId);
+    },
+
+    _normalizeEventTypes: function(types)
+    {
+        if (typeof types === "undefined")
+            types = [ "mouse", "key", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll" ];
+        else if (typeof types === "string")
+            types = [ types ];
+
+        var result = [];
+        for (var i = 0; i < types.length; i++) {
+            if (types[i] === "mouse")
+                result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout");
+            else if (types[i] === "key")
+                result.splice(0, 0, "keydown", "keyup", "keypress");
+            else
+                result.push(types[i]);
+        }
+        return result;
+    },
+
+    _logEvent: function(event)
+    {
+        console.log(event.type, event);
+    }
+}
+
+injectedScript._commandLineAPIImpl = new CommandLineAPIImpl();
+return injectedScript;
+})
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/Inspector.idl b/weinre.build/vendor/webkit/WebCore/inspector/Inspector.idl
new file mode 100644
index 0000000..80c24db
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/Inspector.idl
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+    interface [Conditional=INSPECTOR] Inspector {
+        void addScriptToEvaluateOnLoad(in String scriptSource);
+        void removeAllScriptsToEvaluateOnLoad();
+        void reloadPage(in boolean ignoreCache);
+        void populateScriptObjects();
+
+        void openInInspectedWindow(in String url);
+        void setSearchingForNode(in boolean enabled, out boolean newState);
+        [notify] void frontendReused();
+        [notify] void addNodesToSearchResult(out Array nodeIds);
+        [notify] void bringToFront();
+        [notify] void disconnectFromBackend();
+        [notify] void inspectedURLChanged(out String url);
+        [notify] void domContentEventFired(out double time);
+        [notify] void loadEventFired(out double time);
+        [notify] void reset();
+        [notify] void showPanel(out String panel);
+
+        [notify] void evaluateForTestInFrontend(out long testCallId, out String script);
+        void didEvaluateForTestInFrontend(in long testCallId, in String jsonResult);
+
+        void highlightDOMNode(in long nodeId);
+        void hideDOMNodeHighlight();
+        void highlightFrame(in unsigned long frameId);
+        void hideFrameHighlight();
+        [notify] void updateFocusedNode(out long nodeId);
+
+        void setUserAgentOverride(in String userAgent);
+
+        void getCookies(out Array cookies, out String cookiesString);
+        void deleteCookie(in String cookieName, in String domain);
+
+        // FIXME: dispatch on agents.
+        void startTimelineProfiler();
+        void stopTimelineProfiler();
+
+#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
+        void enableDebugger();
+        void disableDebugger();
+        void enableProfiler();
+        void disableProfiler();
+        void startProfiling();
+        void stopProfiling();
+#endif // ENABLE_JAVASCRIPT_DEBUGGER
+    };
+
+    interface [Conditional=INSPECTOR] Runtime {
+        void evaluate(in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
+        void getCompletions(in String expression, in boolean includeCommandLineAPI, out Value result);
+        void getProperties(in Object objectId, in boolean ignoreHasOwnProperty, in boolean abbreviate, out Value result);
+        void setPropertyValue(in Object objectId, in String propertyName, in String expression, out Value result);
+        void releaseWrapperObjectGroup(in long injectedScriptId, in String objectGroup);
+    };
+
+    interface [Conditional=INSPECTOR] InjectedScript {
+        void evaluateOnSelf(in String functionBody, in Array argumentsArray, out Value result);
+    };
+
+    interface [Conditional=INSPECTOR] Console {
+        void setConsoleMessagesEnabled(in boolean enabled, out boolean newState);
+        [notify] void addConsoleMessage(out Object messageObj);
+        [notify] void updateConsoleMessageExpiredCount(out unsigned long count);
+        [notify] void updateConsoleMessageRepeatCount(out unsigned long count);
+        void clearConsoleMessages();
+        [notify] void consoleMessagesCleared();
+        void setMonitoringXHREnabled(in boolean enabled);
+    };
+
+    interface [Conditional=INSPECTOR] Network {
+        void cachedResources(out Object resources);
+        void resourceContent(in unsigned long frameId, in String url, in boolean base64Encode, out boolean success, out String content);
+        void setExtraHeaders(in Object headers);
+
+        [notify] void frameDetachedFromParent(out unsigned long frameId);
+        [notify] void identifierForInitialRequest(out long identifier, out String url, out Object loader, out Value callStack);
+        [notify] void willSendRequest(out long identifier, out double time, out Object request, out Object redirectResponse);
+        [notify] void markResourceAsCached(out long identifier);
+        [notify] void didReceiveResponse(out long identifier, out double time, out String resourceType, out Object response);
+        [notify] void didReceiveContentLength(out long identifier, out double time, out long lengthReceived);
+        [notify] void didFinishLoading(out long identifier, out double finishTime);
+        [notify] void didFailLoading(out long identifier, out double time, out String localizedDescription);
+        [notify] void didLoadResourceFromMemoryCache(out double time, out Object resource);
+        [notify] void setInitialContent(out long identifier, out String sourceString, out String type);
+        [notify] void didCommitLoadForFrame(out Object frame, out Object loader);
+        [notify] void didCreateWebSocket(out unsigned long identifier, out String requestURL);
+        [notify] void willSendWebSocketHandshakeRequest(out unsigned long identifier, out double time, out Object request);
+        [notify] void didReceiveWebSocketHandshakeResponse(out unsigned long identifier, out double time, out Object response);
+        [notify] void didCloseWebSocket(out unsigned long identifier, out double time);
+    };
+
+#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
+    interface [Conditional=INSPECTOR] Database {
+        void getDatabaseTableNames(in long databaseId, out Array tableNames);
+        void executeSQL(in long databaseId, in String query, out boolean success, out long transactionId);
+
+        [notify] void addDatabase(out Object database);
+        [notify] void selectDatabase(out int databaseId);
+        [notify] void sqlTransactionSucceeded(out long transactionId, out Value columnNames, out Value values);
+        [notify] void sqlTransactionFailed(out long transactionId, out Value sqlError);
+    };
+#endif
+
+#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE
+    interface [Conditional=INSPECTOR] DOMStorage {
+        void getDOMStorageEntries(in long storageId, out Array entries);
+        void setDOMStorageItem(in long storageId, in String key, in String value, out boolean success);
+        void removeDOMStorageItem(in long storageId, in String key, out boolean success);
+        [notify] void addDOMStorage(out Object storage);
+        [notify] void updateDOMStorage(out int storageId);
+        [notify] void selectDOMStorage(out int storageId);
+    };
+#endif
+
+#if defined(ENABLE_OFFLINE_WEB_APPLICATIONS) && ENABLE_OFFLINE_WEB_APPLICATIONS
+    interface [Conditional=INSPECTOR] ApplicationCache {
+        void getApplicationCaches(out Value applicationCaches);
+        [notify] void updateApplicationCacheStatus(out int status);
+        [notify] void updateNetworkState(out boolean isNowOnline);
+    };
+#endif
+
+    interface [Conditional=INSPECTOR] DOM {
+        void getChildNodes(in long nodeId);
+        void setAttribute(in long elementId, in String name, in String value, out boolean success);
+        void removeAttribute(in long elementId, in String name, out boolean success);
+        void setTextNodeValue(in long nodeId, in String value, out boolean success);
+        void getEventListenersForNode(in long nodeId, out long outNodeId, out Array listenersArray);
+        void copyNode(in long nodeId);
+        void removeNode(in long nodeId, out long outNodeId);
+        void changeTagName(in long nodeId, in String newTagName, out long outNodeId);
+        void getOuterHTML(in long nodeId, out String outerHTML);
+        void setOuterHTML(in long nodeId, in String outerHTML, out long outNodeId);
+        void addInspectedNode(in long nodeId);
+        void performSearch(in String query, in boolean runSynchronously);
+        void searchCanceled();
+        void pushNodeByPathToFrontend(in String path, out long nodeId);
+        void resolveNode(in long nodeId, out Value result);
+        void getNodeProperties(in long nodeId, in Array propertiesArray, out Value result);
+        void getNodePrototypes(in long nodeId, out Value result);
+        void pushNodeToFrontend(in Object objectId, out Value result);
+
+        [notify] void setDocument(out Value root); // FIXME: should be requested from the front-end as getDocument.
+        [notify] void attributesUpdated(out long id, out Array attributes);
+        [notify] void characterDataModified(out long id, out String newValue);
+        [notify] void setChildNodes(out long parentId, out Array nodes);
+        [notify] void setDetachedRoot(out Object root);
+        [notify] void childNodeCountUpdated(out long id, out int newValue);
+        [notify] void childNodeInserted(out long parentId, out long prevId, out Object node);
+        [notify] void childNodeRemoved(out long parentId, out long id);
+    };
+
+    interface [Conditional=INSPECTOR] CSS {
+        void getStylesForNode(in long nodeId, out Value styles);
+        void getComputedStyleForNode(in long nodeId, out Value style);
+        void getInlineStyleForNode(in long nodeId, out Value style);
+        void getAllStyles(out Array styleSheetIds);
+        void getStyleSheet(in String styleSheetId, out Value styleSheet);
+        void getStyleSheetText(in String styleSheetId, out String url, out String text);
+        void setStyleSheetText(in String styleSheetId, in String text, out boolean success);
+        void setPropertyText(in Object styleId, in long propertyIndex, in String text, in boolean overwrite, out Value style);
+        void toggleProperty(in Object styleId, in long propertyIndex, in boolean disable, out Value style);
+        void setRuleSelector(in Object ruleId, in String selector, out Value rule);
+        void addRule(in long contextNodeId, in String selector, out Value rule);
+        void getSupportedCSSProperties(out Array cssProperties);
+        void querySelectorAll(in long documentId, in String selector, out Array result);
+    };
+
+    interface [Conditional=INSPECTOR] Timeline {
+        [notify] void timelineProfilerWasStarted();
+        [notify] void timelineProfilerWasStopped();
+        [notify] void addRecordToTimeline(out Object record);
+    };
+
+#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
+    interface [Conditional=INSPECTOR] Debugger {
+        [notify] void debuggerWasEnabled();
+        [notify] void debuggerWasDisabled();
+
+        [notify] void parsedScriptSource(out String sourceID, out String url, out int lineOffset, out int columnOffset, out int length, out int scriptWorldType);
+        [notify] void failedToParseScriptSource(out String url, out String data, out int firstLine, out int errorLine, out String errorMessage);
+
+        void activateBreakpoints();
+        void deactivateBreakpoints();
+
+        void setJavaScriptBreakpoint(in String url, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out Array locations);
+        void setJavaScriptBreakpointBySourceId(in String sourceId, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out int actualLineNumber, out int actualColumnNumber);
+        void removeJavaScriptBreakpoint(in String breakpointId);
+        [notify] void breakpointResolved(out String breakpointId, out String sourceId, out int lineNumber, out int columnNumber);
+        void continueToLocation(in String sourceId, in int lineNumber, in int columnNumber);
+
+        void stepOver();
+        void stepInto();
+        void stepOut();
+        void pause();
+        [notify] void pausedScript(out Object details);
+        void resume();
+        [notify] void resumedScript(); // FIXME: Make this out parameter of resume if possible.
+
+        void editScriptSource(in String sourceID, in String newContent, out boolean success, out String result, out Value newCallFrames);
+        void getScriptSource(in String sourceID, out String scriptSource);
+
+        void setPauseOnExceptionsState(in long pauseOnExceptionsState, out long newState);
+
+        void evaluateOnCallFrame(in Object callFrameId, in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
+        void getCompletionsOnCallFrame(in Object callFrameId, in String expression, in boolean includeCommandLineAPI, out Value result);
+
+#if defined(ENABLE_WORKERS) && ENABLE_WORKERS
+        [notify] void didCreateWorker(out long id, out String url, out boolean isShared);
+        [notify] void didDestroyWorker(out long id);
+#endif // ENABLE_WORKERS
+
+    };
+#endif // ENABLE_JAVASCRIPT_DEBUGGER
+
+#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
+    interface [Conditional=INSPECTOR] BrowserDebugger {
+        void setAllBrowserBreakpoints(in Object breakpoints);
+        void setDOMBreakpoint(in long nodeId, in long type);
+        void removeDOMBreakpoint(in long nodeId, in long type);
+        void setEventListenerBreakpoint(in String eventName);
+        void removeEventListenerBreakpoint(in String eventName);
+        void setXHRBreakpoint(in String url);
+        void removeXHRBreakpoint(in String url);
+    };
+#endif // ENABLE_JAVASCRIPT_DEBUGGER
+
+#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
+    interface [Conditional=INSPECTOR] Profiler {
+        [notify] void profilerWasEnabled();
+        [notify] void profilerWasDisabled();
+
+        void getProfileHeaders(out Array headers);
+        void getProfile(in String type, in unsigned long uid, out Object profile);
+        void removeProfile(in String type, in unsigned long uid);
+        void clearProfiles();
+
+        // FIXME: split into Profiler and HeapProfiler.
+        void takeHeapSnapshot(in boolean detailed);
+        [notify] void addProfileHeader(out Object header);
+        [notify] void addHeapSnapshotChunk(out unsigned long uid, out String chunk);
+        [notify] void finishHeapSnapshot(out unsigned long uid);
+        [notify] void setRecordingProfile(out boolean isProfiling);
+        [notify] void resetProfiles();
+        [notify] void reportHeapSnapshotProgress(out int done, out int total);
+    };
+#endif // ENABLE_JAVASCRIPT_DEBUGGER
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/InspectorFrontendHost.idl b/weinre.build/vendor/webkit/WebCore/inspector/InspectorFrontendHost.idl
new file mode 100644
index 0000000..6853c7d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/InspectorFrontendHost.idl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+    interface [Conditional=INSPECTOR] InspectorFrontendHost {
+        void loaded();
+        void closeWindow();
+        void disconnectFromBackend();
+        void bringToFront();
+        void inspectedURLChanged(in DOMString newURL);
+
+        void requestAttachWindow();
+        void requestDetachWindow();
+        void setAttachedWindowHeight(in unsigned long height);
+        void moveWindowBy(in float x, in float y);
+        void setExtensionAPI(in DOMString script);
+
+        DOMString localizedStringsURL();
+        DOMString hiddenPanels();
+
+        void copyText(in DOMString text);
+
+        [Custom] DOMString platform();
+        [Custom] DOMString port();
+        [Custom] void showContextMenu(in MouseEvent event, in DOMObject items);
+        void sendMessageToBackend(in DOMString message);
+    };
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/JavaScriptCallFrame.idl b/weinre.build/vendor/webkit/WebCore/inspector/JavaScriptCallFrame.idl
new file mode 100644
index 0000000..db0e0a6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/JavaScriptCallFrame.idl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module inspector {
+
+    interface [
+        Conditional=JAVASCRIPT_DEBUGGER,
+        OmitConstructor,
+        DontCheckEnums
+    ] JavaScriptCallFrame {
+
+        // Scope type
+        const unsigned short GLOBAL_SCOPE = 0;
+        const unsigned short LOCAL_SCOPE = 1;
+        const unsigned short WITH_SCOPE = 2;
+        const unsigned short CLOSURE_SCOPE = 3;
+        const unsigned short CATCH_SCOPE = 4;
+
+        [Custom] void evaluate(in DOMString script);
+
+        readonly attribute JavaScriptCallFrame caller;
+        readonly attribute long sourceID;
+        readonly attribute long line;
+        readonly attribute long column;
+        readonly attribute [CustomGetter] Array scopeChain;
+        [Custom] unsigned short scopeType(in int scopeIndex);
+        readonly attribute [CustomGetter] Object thisObject;
+        readonly attribute DOMString functionName;
+        readonly attribute [CustomGetter] DOMString type;
+    };
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfile.idl b/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfile.idl
new file mode 100644
index 0000000..8d4b04a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfile.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+
+    interface [Conditional=JAVASCRIPT_DEBUGGER, OmitConstructor] ScriptProfile {
+        readonly attribute DOMString title;
+        readonly attribute unsigned long uid;
+        readonly attribute ScriptProfileNode head;
+    };
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfileNode.idl b/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfileNode.idl
new file mode 100644
index 0000000..eff17bd
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/ScriptProfileNode.idl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module core {
+
+    interface [Conditional=JAVASCRIPT_DEBUGGER, OmitConstructor] ScriptProfileNode {
+        readonly attribute DOMString functionName;
+        readonly attribute DOMString url;
+        readonly attribute unsigned long lineNumber;
+        readonly attribute double totalTime;
+        readonly attribute double selfTime;
+        readonly attribute unsigned long numberOfCalls;
+        readonly attribute [CustomGetter] Array children;
+        readonly attribute boolean visible;
+        readonly attribute [CustomGetter] unsigned long callUID;
+    };
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ApplicationCacheItemsView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ApplicationCacheItemsView.js
new file mode 100644
index 0000000..b345749
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ApplicationCacheItemsView.js
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ApplicationCacheItemsView = function(treeElement, appcacheDomain)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("storage-view");
+    this.element.addStyleClass("table");
+
+    // FIXME: Delete Button semantics are not yet defined.
+    // FIXME: Needs better tooltip. (Localized)
+    this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
+    this.deleteButton.visible = false;
+    this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+    // FIXME: Refresh Button semantics are not yet defined.
+    // FIXME: Needs better tooltip. (Localized)
+    this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
+    this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+
+    if (Preferences.onlineDetectionEnabled) {
+        this.connectivityIcon = document.createElement("img");
+        this.connectivityIcon.className = "storage-application-cache-connectivity-icon";
+        this.connectivityIcon.src = "";
+        this.connectivityMessage = document.createElement("span");
+        this.connectivityMessage.className = "storage-application-cache-connectivity";
+        this.connectivityMessage.textContent = "";
+    }
+
+    this.divider = document.createElement("span");
+    this.divider.className = "status-bar-item status-bar-divider";
+
+    this.statusIcon = document.createElement("img");
+    this.statusIcon.className = "storage-application-cache-status-icon";
+    this.statusIcon.src = "";
+    this.statusMessage = document.createElement("span");
+    this.statusMessage.className = "storage-application-cache-status";
+    this.statusMessage.textContent = "";
+
+    this._treeElement = treeElement;
+    this._appcacheDomain = appcacheDomain;
+
+    this._emptyMsgElement = document.createElement("div");
+    this._emptyMsgElement.className = "storage-empty-view";
+    this._emptyMsgElement.textContent = WebInspector.UIString("No Application Cache information available.");
+    this.element.appendChild(this._emptyMsgElement);
+
+    this.updateStatus(applicationCache.UNCACHED);
+}
+
+WebInspector.ApplicationCacheItemsView.prototype = {
+    get statusBarItems()
+    {
+        if (Preferences.onlineDetectionEnabled) {
+            return [
+                this.refreshButton.element, this.deleteButton.element,
+                this.connectivityIcon, this.connectivityMessage, this.divider,
+                this.statusIcon, this.statusMessage
+            ];
+        } else {
+            return [
+                this.refreshButton.element, this.deleteButton.element, this.divider,
+                this.statusIcon, this.statusMessage
+            ];
+        }
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this.updateNetworkState(navigator.onLine);
+        this._update();
+    },
+
+    hide: function()
+    {
+        WebInspector.View.prototype.hide.call(this);
+        this.deleteButton.visible = false;
+    },
+
+    updateStatus: function(status)
+    {
+        var statusInformation = {};
+        statusInformation[applicationCache.UNCACHED]    = { src: "Images/warningOrangeDot.png", text: "UNCACHED"    };
+        statusInformation[applicationCache.IDLE]        = { src: "Images/warningOrangeDot.png", text: "IDLE"        };
+        statusInformation[applicationCache.CHECKING]    = { src: "Images/successGreenDot.png",  text: "CHECKING"    };
+        statusInformation[applicationCache.DOWNLOADING] = { src: "Images/successGreenDot.png",  text: "DOWNLOADING" };
+        statusInformation[applicationCache.UPDATEREADY] = { src: "Images/successGreenDot.png",  text: "UPDATEREADY" };
+        statusInformation[applicationCache.OBSOLETE]    = { src: "Images/errorRedDot.png",      text: "OBSOLETE"    };
+
+        var info = statusInformation[status];
+        if (!info) {
+            console.error("Unknown Application Cache Status was Not Handled: %d", status);
+            return;
+        }
+
+        this.statusIcon.src = info.src;
+        this.statusMessage.textContent = info.text;
+    },
+
+    updateNetworkState: function(isNowOnline)
+    {
+        if (Preferences.onlineDetectionEnabled) {
+            if (isNowOnline) {
+                this.connectivityIcon.src = "Images/successGreenDot.png";
+                this.connectivityMessage.textContent = WebInspector.UIString("Online");
+            } else {
+                this.connectivityIcon.src = "Images/errorRedDot.png";
+                this.connectivityMessage.textContent = WebInspector.UIString("Offline");
+            }
+        }
+    },
+
+    _update: function()
+    {
+        WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync(this._updateCallback.bind(this));
+    },
+
+    _updateCallback: function(applicationCaches)
+    {
+        // FIXME: applicationCaches is just one cache.
+        // FIXME: are these variables needed anywhere else?
+        this._manifest = applicationCaches.manifest;
+        this._creationTime = applicationCaches.creationTime;
+        this._updateTime = applicationCaches.updateTime;
+        this._size = applicationCaches.size;
+        this._resources = applicationCaches.resources;
+        var lastPathComponent = applicationCaches.lastPathComponent;
+
+        if (!this._manifest) {
+            this._emptyMsgElement.removeStyleClass("hidden");
+            this.deleteButton.visible = false;
+            if (this._dataGrid)
+                this._dataGrid.element.addStyleClass("hidden");
+            return;
+        }
+
+        if (!this._dataGrid)
+            this._createDataGrid();
+
+        this._populateDataGrid();
+        this._dataGrid.autoSizeColumns(20, 80);
+        this._dataGrid.element.removeStyleClass("hidden");
+        this._emptyMsgElement.addStyleClass("hidden");
+        this.deleteButton.visible = true;
+
+        var totalSizeString = Number.bytesToString(this._size);
+        this._treeElement.subtitle = WebInspector.UIString("%s (%s)", lastPathComponent, totalSizeString);
+
+        // FIXME: For Chrome, put creationTime and updateTime somewhere.
+        // NOTE: localizedString has not yet been added.
+        // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, this._creationTime, this._updateTime);
+    },
+
+    _createDataGrid: function()
+    {
+        var columns = { 0: {}, 1: {}, 2: {} };
+        columns[0].title = WebInspector.UIString("Resource");
+        columns[0].sort = "ascending";
+        columns[0].sortable = true;
+        columns[1].title = WebInspector.UIString("Type");
+        columns[1].sortable = true;
+        columns[2].title = WebInspector.UIString("Size");
+        columns[2].aligned = "right";
+        columns[2].sortable = true;
+        this._dataGrid = new WebInspector.DataGrid(columns);
+        this.element.appendChild(this._dataGrid.element);
+        this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this);
+        this._dataGrid.updateWidths();
+    },
+
+    _populateDataGrid: function()
+    {
+        var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null;
+        var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;
+
+        function numberCompare(field, resource1, resource2)
+        {
+            return sortDirection * (resource1[field] - resource2[field]);
+        }
+        function localeCompare(field, resource1, resource2)
+        {
+             return sortDirection * (resource1[field] + "").localeCompare(resource2[field] + "")
+        }
+
+        var comparator;
+        switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
+            case 0: comparator = localeCompare.bind(this, "name"); break;
+            case 1: comparator = localeCompare.bind(this, "type"); break;
+            case 2: comparator = numberCompare.bind(this, "size"); break;
+            default: localeCompare.bind(this, "resource"); // FIXME: comparator = ?
+        }
+
+        this._resources.sort(comparator);
+        this._dataGrid.removeChildren();
+
+        var nodeToSelect;
+        for (var i = 0; i < this._resources.length; ++i) {
+            var data = {};
+            var resource = this._resources[i];
+            data[0] = resource.name;
+            data[1] = resource.type;
+            data[2] = Number.bytesToString(resource.size);
+            var node = new WebInspector.DataGridNode(data);
+            node.resource = resource;
+            node.selectable = true;
+            this._dataGrid.appendChild(node);
+            if (resource === selectedResource) {
+                nodeToSelect = node;
+                nodeToSelect.selected = true;
+            }
+        }
+
+        if (!nodeToSelect)
+            this._dataGrid.children[0].selected = true;
+    },
+
+    resize: function()
+    {
+        if (this._dataGrid)
+            this._dataGrid.updateWidths();
+    },
+
+    _deleteButtonClicked: function(event)
+    {
+        if (!this._dataGrid || !this._dataGrid.selectedNode)
+            return;
+
+        // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
+        this._deleteCallback(this._dataGrid.selectedNode);
+    },
+
+    _deleteCallback: function(node)
+    {
+        // FIXME: Should we delete a single (selected) resource or all resources?
+        // InspectorBackend.deleteCachedResource(...)
+        // this._update();
+    },
+
+    _refreshButtonClicked: function(event)
+    {
+        // FIXME: Is this a refresh button or a re-fetch manifest button?
+        // this._update();
+    }
+}
+
+WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditCategories.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditCategories.js
new file mode 100644
index 0000000..01b5ff9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditCategories.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditCategories.PagePerformance = function() {
+    WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.PagePerformance.AuditCategoryName);
+}
+
+WebInspector.AuditCategories.PagePerformance.AuditCategoryName = "Web Page Performance";
+
+WebInspector.AuditCategories.PagePerformance.prototype = {
+    initialize: function()
+    {
+        this.addRule(new WebInspector.AuditRules.UnusedCssRule(), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.CssInHeadRule(), WebInspector.AuditRule.Severity.Severe);
+        this.addRule(new WebInspector.AuditRules.StylesScriptsOrderRule(), WebInspector.AuditRule.Severity.Severe);
+    }
+}
+
+WebInspector.AuditCategories.PagePerformance.prototype.__proto__ = WebInspector.AuditCategory.prototype;
+
+WebInspector.AuditCategories.NetworkUtilization = function() {
+    WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName);
+}
+
+WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName = "Network Utilization";
+
+WebInspector.AuditCategories.NetworkUtilization.prototype = {
+    initialize: function()
+    {
+        this.addRule(new WebInspector.AuditRules.GzipRule(), WebInspector.AuditRule.Severity.Severe);
+        this.addRule(new WebInspector.AuditRules.ImageDimensionsRule(), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.CookieSizeRule(400), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.StaticCookielessRule(5), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.CombineJsResourcesRule(2), WebInspector.AuditRule.Severity.Severe);
+        this.addRule(new WebInspector.AuditRules.CombineCssResourcesRule(2), WebInspector.AuditRule.Severity.Severe);
+        this.addRule(new WebInspector.AuditRules.MinimizeDnsLookupsRule(4), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.ParallelizeDownloadRule(4, 10, 0.5), WebInspector.AuditRule.Severity.Warning);
+        this.addRule(new WebInspector.AuditRules.BrowserCacheControlRule(), WebInspector.AuditRule.Severity.Severe);
+        this.addRule(new WebInspector.AuditRules.ProxyCacheControlRule(), WebInspector.AuditRule.Severity.Warning);
+    }
+}
+
+WebInspector.AuditCategories.NetworkUtilization.prototype.__proto__ = WebInspector.AuditCategory.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditFormatters.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditFormatters.js
new file mode 100644
index 0000000..1bc1803
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditFormatters.js
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.applyFormatters = function(value)
+{
+    var formatter;
+    var type = typeof value;
+    var args;
+
+    switch (type) {
+        case "string":
+        case "boolean":
+        case "number":
+            formatter = WebInspector.AuditFormatters.text;
+            args = [ value.toString() ];
+            break;
+
+        case "object":
+            if (value instanceof Array) {
+                formatter = WebInspector.AuditFormatters.concat;
+                args = value;
+            } else if (value.type && value.arguments) {
+                formatter = WebInspector.AuditFormatters[value.type];
+                args = value.arguments;
+            }
+    }
+    if (!formatter)
+        throw "Invalid value or formatter: " + type + JSON.stringify(value);
+
+    return formatter.apply(null, args);
+}
+
+WebInspector.AuditFormatters = {
+    text: function(text)
+    {
+        return document.createTextNode(text);
+    },
+
+    snippet: function(snippetText)
+    {
+        var div = document.createElement("div");
+        div.innerText = snippetText;
+        div.className = "source-code";
+        return div;
+    },
+
+    concat: function()
+    {
+        var parent = document.createElement("span");
+        for (var arg = 0; arg < arguments.length; ++arg)
+            parent.appendChild(WebInspector.applyFormatters(arguments[arg]));
+        return parent;
+    },
+
+    url: function(url, displayText, allowExternalNavigation)
+    {
+        var a = document.createElement("a");
+        a.href = url;
+        a.title = url;
+        a.textContent = displayText || url;
+        if (allowExternalNavigation)
+            a.target = "_blank";
+        return a;
+    }
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditLauncherView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditLauncherView.js
new file mode 100644
index 0000000..df16a41
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditLauncherView.js
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditLauncherView = function(runnerCallback)
+{
+    WebInspector.View.call(this);
+    this._runnerCallback = runnerCallback;
+    this._categoryIdPrefix = "audit-category-item-";
+    this._auditRunning = false;
+
+    this.element.addStyleClass("audit-launcher-view");
+
+    this._contentElement = document.createElement("div");
+    this._contentElement.className = "audit-launcher-view-content";
+    this.element.appendChild(this._contentElement);
+    this._boundCategoryClickListener = this._categoryClicked.bind(this);
+
+    this._resetResourceCount();
+
+    this._sortedCategories = [];
+
+    this._headerElement = document.createElement("h1");
+    this._headerElement.className = "no-audits";
+    this._headerElement.textContent = WebInspector.UIString("No audits to run");
+    this._contentElement.appendChild(this._headerElement);
+
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceFinished, this);
+}
+
+WebInspector.AuditLauncherView.prototype = {
+    _resetResourceCount: function()
+    {
+        this._loadedResources = 0;
+        this._totalResources = 0;
+    },
+
+    _onResourceStarted: function(event)
+    {
+        var resource = event.data;
+        // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
+        if (resource.type === WebInspector.Resource.Type.WebSocket)
+            return;
+        ++this._totalResources;
+        this._updateResourceProgress();
+    },
+
+    _onResourceFinished: function(event)
+    {
+        var resource = event.data;
+        // See resorceStarted for details.
+        if (resource.type === WebInspector.Resource.Type.WebSocket)
+            return;
+        ++this._loadedResources;
+        this._updateResourceProgress();
+    },
+
+    addCategory: function(category)
+    {
+        if (!this._sortedCategories.length)
+            this._createLauncherUI();
+
+        var categoryElement = this._createCategoryElement(category.displayName, category.id);
+        category._checkboxElement = categoryElement.firstChild;
+        if (this._selectAllCheckboxElement.checked) {
+            category._checkboxElement.checked = true;
+            ++this._currentCategoriesCount;
+        }
+
+        function compareCategories(a, b)
+        {
+            var aTitle = a.displayName || "";
+            var bTitle = b.displayName || "";
+            return aTitle.localeCompare(bTitle);
+        }
+        var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
+        this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
+        this._sortedCategories.splice(insertBefore, 0, category);
+        this._updateButton();
+    },
+
+    _setAuditRunning: function(auditRunning)
+    {
+        if (this._auditRunning === auditRunning)
+            return;
+        this._auditRunning = auditRunning;
+        this._updateButton();
+        this._updateResourceProgress();
+    },
+
+    _launchButtonClicked: function(event)
+    {
+        var catIds = [];
+        var childNodes = this._categoriesElement.childNodes;
+        for (var category = 0; category < this._sortedCategories.length; ++category) {
+            if (this._sortedCategories[category]._checkboxElement.checked)
+                catIds.push(this._sortedCategories[category].id);
+        }
+
+        this._setAuditRunning(true);
+        this._runnerCallback(catIds, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
+    },
+
+    _selectAllClicked: function(checkCategories)
+    {
+        var childNodes = this._categoriesElement.childNodes;
+        for (var i = 0, length = childNodes.length; i < length; ++i)
+            childNodes[i].firstChild.checked = checkCategories;
+        this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
+        this._updateButton();
+    },
+
+    _categoryClicked: function(event)
+    {
+        this._currentCategoriesCount += event.target.checked ? 1 : -1;
+        this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
+        this._updateButton();
+    },
+
+    _createCategoryElement: function(title, id)
+    {
+        var labelElement = document.createElement("label");
+        labelElement.id = this._categoryIdPrefix + id;
+
+        var element = document.createElement("input");
+        element.type = "checkbox";
+        if (id !== "")
+            element.addEventListener("click", this._boundCategoryClickListener, false);
+        labelElement.appendChild(element);
+        labelElement.appendChild(document.createTextNode(title));
+
+        return labelElement;
+    },
+
+    _createLauncherUI: function()
+    {
+        this._headerElement = document.createElement("h1");
+        this._headerElement.textContent = WebInspector.UIString("Select audits to run");
+
+        for (var child = 0; child < this._contentElement.children.length; ++child)
+            this._contentElement.removeChild(this._contentElement.children[child]);
+
+        this._contentElement.appendChild(this._headerElement);
+
+        function handleSelectAllClick(event)
+        {
+            this._selectAllClicked(event.target.checked);
+        }
+        var categoryElement = this._createCategoryElement(WebInspector.UIString("Select All"), "");
+        categoryElement.id = "audit-launcher-selectall";
+        this._selectAllCheckboxElement = categoryElement.firstChild;
+        this._selectAllCheckboxElement.checked = true;
+        this._selectAllCheckboxElement.addEventListener("click", handleSelectAllClick.bind(this), false);
+        this._contentElement.appendChild(categoryElement);
+
+        this._categoriesElement = document.createElement("div");
+        this._categoriesElement.className = "audit-categories-container";
+        this._contentElement.appendChild(this._categoriesElement);
+
+        this._currentCategoriesCount = 0;
+
+        var flexibleSpaceElement = document.createElement("div");
+        flexibleSpaceElement.className = "flexible-space";
+        this._contentElement.appendChild(flexibleSpaceElement);
+
+        this._buttonContainerElement = document.createElement("div");
+        this._buttonContainerElement.className = "button-container";
+
+        var labelElement = document.createElement("label");
+        this._auditPresentStateElement = document.createElement("input");
+        this._auditPresentStateElement.name = "audit-mode";
+        this._auditPresentStateElement.type = "radio";
+        this._auditPresentStateElement.checked = true;
+        this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State"));
+        labelElement.appendChild(this._auditPresentStateElement);
+        labelElement.appendChild(this._auditPresentStateLabelElement);
+        this._buttonContainerElement.appendChild(labelElement);
+
+        labelElement = document.createElement("label");
+        this.auditReloadedStateElement = document.createElement("input");
+        this.auditReloadedStateElement.name = "audit-mode";
+        this.auditReloadedStateElement.type = "radio";
+        labelElement.appendChild(this.auditReloadedStateElement);
+        labelElement.appendChild(document.createTextNode("Reload Page and Audit on Load"));
+        this._buttonContainerElement.appendChild(labelElement);
+
+        this._launchButton = document.createElement("button");
+        this._launchButton.type = "button";
+        this._launchButton.textContent = WebInspector.UIString("Run");
+        this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false);
+        this._buttonContainerElement.appendChild(this._launchButton);
+
+        this._resourceProgressContainer = document.createElement("span");
+        this._resourceProgressContainer.className = "resource-progress";
+        var resourceProgressImage = document.createElement("img");
+        this._resourceProgressContainer.appendChild(resourceProgressImage);
+        this._resourceProgressTextElement = document.createElement("span");
+        this._resourceProgressContainer.appendChild(this._resourceProgressTextElement);
+        this._buttonContainerElement.appendChild(this._resourceProgressContainer);
+
+        this._contentElement.appendChild(this._buttonContainerElement);
+
+        this._selectAllClicked(this._selectAllCheckboxElement.checked);
+        this._updateButton();
+        this._updateResourceProgress();
+    },
+
+    _updateResourceProgress: function()
+    {
+        if (!this._resourceProgressContainer)
+            return;
+
+        if (!this._auditRunning) {
+            this._resetResourceCount();
+            this._resourceProgressContainer.addStyleClass("hidden");
+        } else
+            this._resourceProgressContainer.removeStyleClass("hidden");
+        this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources);
+    },
+
+    _updateButton: function()
+    {
+        this._launchButton.disabled = !this._currentCategoriesCount || this._auditRunning;
+    }
+}
+
+WebInspector.AuditLauncherView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditResultView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditResultView.js
new file mode 100644
index 0000000..5771684
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditResultView.js
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditResultView = function(categoryResults)
+{
+    WebInspector.View.call(this);
+    this.element.className = "audit-result-view";
+
+    function categorySorter(a, b) {
+        return (a.title || "").localeCompare(b.title || "");
+    }
+    categoryResults.sort(categorySorter);
+    for (var i = 0; i < categoryResults.length; ++i)
+        this.element.appendChild(new WebInspector.AuditCategoryResultPane(categoryResults[i]).element);
+}
+
+WebInspector.AuditResultView.prototype.__proto__ = WebInspector.View.prototype;
+
+
+WebInspector.AuditCategoryResultPane = function(categoryResult)
+{
+    WebInspector.SidebarPane.call(this, categoryResult.title);
+    var treeOutlineElement = document.createElement("ol");
+    this.bodyElement.addStyleClass("audit-result-tree");
+    this.bodyElement.appendChild(treeOutlineElement);
+
+    this._treeOutline = new TreeOutline(treeOutlineElement);
+    this._treeOutline.expandTreeElementsWhenArrowing = true;
+
+    function ruleSorter(a, b)
+    {
+        var result = WebInspector.AuditRule.SeverityOrder[a.severity || 0] - WebInspector.AuditRule.SeverityOrder[b.severity || 0];
+        if (!result)
+            result = (a.value || "").localeCompare(b.value || "");
+        return result;
+    }
+
+    categoryResult.ruleResults.sort(ruleSorter);
+
+    for (var i = 0; i < categoryResult.ruleResults.length; ++i) {
+        var ruleResult = categoryResult.ruleResults[i];
+        var treeElement = this._appendResult(this._treeOutline, ruleResult);
+        treeElement.listItemElement.addStyleClass("audit-result");
+
+        if (ruleResult.severity) {
+            var severityElement = document.createElement("img");
+            severityElement.className = "severity-" + ruleResult.severity;
+            treeElement.listItemElement.appendChild(severityElement);
+        }
+    }
+    this.expand();
+}
+
+WebInspector.AuditCategoryResultPane.prototype = {
+    _appendResult: function(parentTreeElement, result)
+    {
+        var title = "";
+        
+        if (typeof result.value === "string") {
+            title = result.value;
+            if (result.violationCount)
+                title = String.sprintf("%s (%d)", title, result.violationCount);
+        }
+
+        var treeElement = new TreeElement(null, null, !!result.children);
+        treeElement.titleHTML = title;
+        parentTreeElement.appendChild(treeElement);
+
+        if (result.className)
+            treeElement.listItemElement.addStyleClass(result.className);
+        if (typeof result.value !== "string")
+            treeElement.listItemElement.appendChild(WebInspector.applyFormatters(result.value));
+
+        if (result.children) {
+            for (var i = 0; i < result.children.length; ++i)
+                this._appendResult(treeElement, result.children[i]);
+        }
+        if (result.expanded) {
+            treeElement.listItemElement.removeStyleClass("parent");
+            treeElement.listItemElement.addStyleClass("parent-expanded");
+            treeElement.expand();
+        }
+        return treeElement;
+    }
+}
+
+WebInspector.AuditCategoryResultPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditRules.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditRules.js
new file mode 100644
index 0000000..c122ba4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditRules.js
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
+
+WebInspector.AuditRules.CacheableResponseCodes =
+{
+    200: true,
+    203: true,
+    206: true,
+    300: true,
+    301: true,
+    410: true,
+
+    304: true // Underlying resource is cacheable
+}
+
+WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, needFullResources)
+{
+    var domainToResourcesMap = {};
+    for (var i = 0, size = resources.length; i < size; ++i) {
+        var resource = resources[i];
+        if (types && types.indexOf(resource.type) === -1)
+            continue;
+        var parsedURL = resource.url.asParsedURL();
+        if (!parsedURL)
+            continue;
+        var domain = parsedURL.host;
+        var domainResources = domainToResourcesMap[domain];
+        if (domainResources === undefined) {
+          domainResources = [];
+          domainToResourcesMap[domain] = domainResources;
+        }
+        domainResources.push(needFullResources ? resource : resource.url);
+    }
+    return domainToResourcesMap;
+}
+
+WebInspector.AuditRules.evaluateInTargetWindow = function(func, args, callback)
+{
+    InspectorBackend.evaluateOnSelf(func.toString(), args, callback);
+}
+
+
+WebInspector.AuditRules.GzipRule = function()
+{
+    WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
+}
+
+WebInspector.AuditRules.GzipRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        var totalSavings = 0;
+        var compressedSize = 0;
+        var candidateSize = 0;
+        var summary = result.addChild("", true);
+        for (var i = 0, length = resources.length; i < length; ++i) {
+            var resource = resources[i];
+            if (this._shouldCompress(resource)) {
+                var size = resource.resourceSize;
+                candidateSize += size;
+                if (this._isCompressed(resource)) {
+                    compressedSize += size;
+                    continue;
+                }
+                var savings = 2 * size / 3;
+                totalSavings += savings;
+                summary.addChild(String.sprintf("%s could save ~%s", WebInspector.AuditRuleResult.linkifyDisplayName(resource.url), Number.bytesToString(savings)));
+                result.violationCount++;
+            }
+        }
+        if (!totalSavings)
+            return callback(null);
+        summary.value = String.sprintf("Compressing the following resources with gzip could reduce their transfer size by about two thirds (~%s):", Number.bytesToString(totalSavings));
+        callback(result);
+    },
+
+    _isCompressed: function(resource)
+    {
+        var encoding = resource.responseHeaders["Content-Encoding"];
+        return encoding === "gzip" || encoding === "deflate";
+    },
+
+    _shouldCompress: function(resource)
+    {
+        return WebInspector.Resource.Type.isTextType(resource.type) && resource.domain && resource.resourceSize !== undefined && resource.resourceSize > 150;
+    }
+}
+
+WebInspector.AuditRules.GzipRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type, resourceTypeName, allowedPerDomain)
+{
+    WebInspector.AuditRule.call(this, id, name);
+    this._type = type;
+    this._resourceTypeName = resourceTypeName;
+    this._allowedPerDomain = allowedPerDomain;
+}
+
+WebInspector.AuditRules.CombineExternalResourcesRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type]);
+        var penalizedResourceCount = 0;
+        // TODO: refactor according to the chosen i18n approach
+        var summary = result.addChild("", true);
+        for (var domain in domainToResourcesMap) {
+            var domainResources = domainToResourcesMap[domain];
+            var extraResourceCount = domainResources.length - this._allowedPerDomain;
+            if (extraResourceCount <= 0)
+                continue;
+            penalizedResourceCount += extraResourceCount - 1;
+            summary.addChild(String.sprintf("%d %s resources served from %s.", domainResources.length, this._resourceTypeName, WebInspector.AuditRuleResult.resourceDomain(domain)));
+            result.violationCount += domainResources.length;
+        }
+        if (!penalizedResourceCount)
+            return callback(null);
+
+        summary.value = "There are multiple resources served from same domain. Consider combining them into as few files as possible.";
+        callback(result);
+    }
+}
+
+WebInspector.AuditRules.CombineExternalResourcesRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CombineJsResourcesRule = function(allowedPerDomain) {
+    WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externaljs", "Combine external JavaScript", WebInspector.Resource.Type.Script, "JavaScript", allowedPerDomain);
+}
+
+WebInspector.AuditRules.CombineJsResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;
+
+
+WebInspector.AuditRules.CombineCssResourcesRule = function(allowedPerDomain) {
+    WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externalcss", "Combine external CSS", WebInspector.Resource.Type.Stylesheet, "CSS", allowedPerDomain);
+}
+
+WebInspector.AuditRules.CombineCssResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;
+
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule = function(hostCountThreshold) {
+    WebInspector.AuditRule.call(this, "network-minimizelookups", "Minimize DNS lookups");
+    this._hostCountThreshold = hostCountThreshold;
+}
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        var summary = result.addChild("");
+        var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined);
+        for (var domain in domainToResourcesMap) {
+            if (domainToResourcesMap[domain].length > 1)
+                continue;
+            var parsedURL = domain.asParsedURL();
+            if (!parsedURL)
+                continue;
+            if (!parsedURL.host.search(WebInspector.AuditRules.IPAddressRegexp))
+                continue; // an IP address
+            summary.addSnippet(match[2]);
+            result.violationCount++;
+        }
+        if (!summary.children || summary.children.length <= this._hostCountThreshold)
+            return callback(null);
+
+        summary.value = "The following domains only serve one resource each. If possible, avoid the extra DNS lookups by serving these resources from existing domains.";
+        callback(result);
+    }
+}
+
+WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.ParallelizeDownloadRule = function(optimalHostnameCount, minRequestThreshold, minBalanceThreshold)
+{
+    WebInspector.AuditRule.call(this, "network-parallelizehosts", "Parallelize downloads across hostnames");
+    this._optimalHostnameCount = optimalHostnameCount;
+    this._minRequestThreshold = minRequestThreshold;
+    this._minBalanceThreshold = minBalanceThreshold;
+}
+
+
+WebInspector.AuditRules.ParallelizeDownloadRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        function hostSorter(a, b)
+        {
+            var aCount = domainToResourcesMap[a].length;
+            var bCount = domainToResourcesMap[b].length;
+            return (aCount < bCount) ? 1 : (aCount == bCount) ? 0 : -1;
+        }
+
+        var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(
+            resources,
+            [WebInspector.Resource.Type.Stylesheet, WebInspector.Resource.Type.Image],
+            true);
+
+        var hosts = [];
+        for (var url in domainToResourcesMap)
+            hosts.push(url);
+
+        if (!hosts.length)
+            return callback(null); // no hosts (local file or something)
+
+        hosts.sort(hostSorter);
+
+        var optimalHostnameCount = this._optimalHostnameCount;
+        if (hosts.length > optimalHostnameCount)
+            hosts.splice(optimalHostnameCount);
+
+        var busiestHostResourceCount = domainToResourcesMap[hosts[0]].length;
+        var resourceCountAboveThreshold = busiestHostResourceCount - this._minRequestThreshold;
+        if (resourceCountAboveThreshold <= 0)
+            return callback(null);
+
+        var avgResourcesPerHost = 0;
+        for (var i = 0, size = hosts.length; i < size; ++i)
+            avgResourcesPerHost += domainToResourcesMap[hosts[i]].length;
+
+        // Assume optimal parallelization.
+        avgResourcesPerHost /= optimalHostnameCount;
+        avgResourcesPerHost = Math.max(avgResourcesPerHost, 1);
+
+        var pctAboveAvg = (resourceCountAboveThreshold / avgResourcesPerHost) - 1.0;
+        var minBalanceThreshold = this._minBalanceThreshold;
+        if (pctAboveAvg < minBalanceThreshold)
+            return callback(null);
+
+        var resourcesOnBusiestHost = domainToResourcesMap[hosts[0]];
+        var entry = result.addChild(String.sprintf("This page makes %d parallelizable requests to %s. Increase download parallelization by distributing the following requests across multiple hostnames.", busiestHostResourceCount, hosts[0]), true);
+        for (var i = 0; i < resourcesOnBusiestHost.length; ++i)
+            entry.addURL(resourcesOnBusiestHost[i].url);
+
+        result.violationCount = resourcesOnBusiestHost.length;
+        callback(result);
+    }
+}
+
+WebInspector.AuditRules.ParallelizeDownloadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+// The reported CSS rule size is incorrect (parsed != original in WebKit),
+// so use percentages instead, which gives a better approximation.
+WebInspector.AuditRules.UnusedCssRule = function()
+{
+    WebInspector.AuditRule.call(this, "page-unusedcss", "Remove unused CSS rules");
+}
+
+WebInspector.AuditRules.UnusedCssRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        var self = this;
+
+        function evalCallback(styleSheets) {
+            if (!styleSheets.length)
+                return callback(null);
+
+            var pseudoSelectorRegexp = /:hover|:link|:active|:visited|:focus|:before|:after/;
+            var selectors = [];
+            var testedSelectors = {};
+            for (var i = 0; i < styleSheets.length; ++i) {
+                var styleSheet = styleSheets[i];
+                for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
+                    var selectorText = styleSheet.rules[curRule].selectorText;
+                    if (selectorText.match(pseudoSelectorRegexp) || testedSelectors[selectorText])
+                        continue;
+                    selectors.push(selectorText);
+                    testedSelectors[selectorText] = 1;
+                }
+            }
+
+            function selectorsCallback(callback, styleSheets, testedSelectors, foundSelectors)
+            {
+                var inlineBlockOrdinal = 0;
+                var totalStylesheetSize = 0;
+                var totalUnusedStylesheetSize = 0;
+                var summary;
+
+                for (var i = 0; i < styleSheets.length; ++i) {
+                    var styleSheet = styleSheets[i];
+                    var stylesheetSize = 0;
+                    var unusedStylesheetSize = 0;
+                    var unusedRules = [];
+                    for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
+                        var rule = styleSheet.rules[curRule];
+                        // Exact computation whenever source ranges are available.
+                        var textLength = (rule.selectorRange && rule.style.properties.endOffset) ? rule.style.properties.endOffset - rule.selectorRange.start + 1 : 0;
+                        if (!textLength && rule.style.cssText)
+                            textLength = rule.style.cssText.length + rule.selectorText.length;
+                        stylesheetSize += textLength;
+                        if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selectorText])
+                            continue;
+                        unusedStylesheetSize += textLength;
+                        unusedRules.push(rule.selectorText);
+                    }
+                    totalStylesheetSize += stylesheetSize;
+                    totalUnusedStylesheetSize += unusedStylesheetSize;
+
+                    if (!unusedRules.length)
+                        continue;
+
+                    var resource = WebInspector.resourceForURL(styleSheet.sourceURL);
+                    var isInlineBlock = resource && resource.type == WebInspector.Resource.Type.Document;
+                    var url = !isInlineBlock ? WebInspector.AuditRuleResult.linkifyDisplayName(styleSheet.sourceURL) : String.sprintf("Inline block #%d", ++inlineBlockOrdinal);
+                    var pctUnused = Math.round(100 * unusedStylesheetSize / stylesheetSize);
+                    if (!summary)
+                        summary = result.addChild("", true);
+                    var entry = summary.addChild(String.sprintf("%s: %s (%d%%) is not used by the current page.", url, Number.bytesToString(unusedStylesheetSize), pctUnused));
+
+                    for (var j = 0; j < unusedRules.length; ++j)
+                        entry.addSnippet(unusedRules[j]);
+
+                    result.violationCount += unusedRules.length;
+                }
+
+                if (!totalUnusedStylesheetSize)
+                    return callback(null);
+
+                var totalUnusedPercent = Math.round(100 * totalUnusedStylesheetSize / totalStylesheetSize);
+                summary.value = String.sprintf("%s (%d%%) of CSS is not used by the current page.", Number.bytesToString(totalUnusedStylesheetSize), totalUnusedPercent);
+
+                callback(result);
+            }
+
+            function routine(selectorArray)
+            {
+                var result = {};
+                for (var i = 0; i < selectorArray.length; ++i) {
+                    try {
+                        if (document.querySelector(selectorArray[i]))
+                            result[selectorArray[i]] = true;
+                    } catch(e) {
+                        // Ignore and mark as unused.
+                    }
+                }
+                return result;
+            }
+
+            WebInspector.AuditRules.evaluateInTargetWindow(routine, [selectors], selectorsCallback.bind(null, callback, styleSheets, testedSelectors));
+        }
+
+        function styleSheetCallback(styleSheets, continuation, styleSheet)
+        {
+            if (styleSheet)
+                styleSheets.push(styleSheet);
+            if (continuation)
+                continuation(styleSheets);
+        }
+
+        function allStylesCallback(styleSheetIds)
+        {
+            if (!styleSheetIds || !styleSheetIds.length)
+                return evalCallback([]);
+            var styleSheets = [];
+            for (var i = 0; i < styleSheetIds.length; ++i)
+                WebInspector.CSSStyleSheet.createForId(styleSheetIds[i], styleSheetCallback.bind(null, styleSheets, i == styleSheetIds.length - 1 ? evalCallback : null));
+        }
+
+        InspectorBackend.getAllStyles(allStylesCallback);
+    }
+}
+
+WebInspector.AuditRules.UnusedCssRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CacheControlRule = function(id, name)
+{
+    WebInspector.AuditRule.call(this, id, name);
+}
+
+WebInspector.AuditRules.CacheControlRule.MillisPerMonth = 1000 * 60 * 60 * 24 * 30;
+
+WebInspector.AuditRules.CacheControlRule.prototype = {
+
+    doRun: function(resources, result, callback)
+    {
+        var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(resources);
+        if (cacheableAndNonCacheableResources[0].length)
+            this.runChecks(cacheableAndNonCacheableResources[0], result);
+        this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], result);
+
+        callback(result);
+    },
+
+    handleNonCacheableResources: function()
+    {
+    },
+
+    _cacheableAndNonCacheableResources: function(resources)
+    {
+        var processedResources = [[], []];
+        for (var i = 0; i < resources.length; ++i) {
+            var resource = resources[i];
+            if (!this.isCacheableResource(resource))
+                continue;
+            if (this._isExplicitlyNonCacheable(resource))
+                processedResources[1].push(resource);
+            else
+                processedResources[0].push(resource);
+        }
+        return processedResources;
+    },
+
+    execCheck: function(messageText, resourceCheckFunction, resources, result)
+    {
+        var resourceCount = resources.length;
+        var urls = [];
+        for (var i = 0; i < resourceCount; ++i) {
+            if (resourceCheckFunction.call(this, resources[i]))
+                urls.push(resources[i].url);
+        }
+        if (urls.length) {
+            var entry = result.addChild(messageText, true);
+            entry.addURLs(urls);
+            result.violationCount += urls.length;
+        }
+    },
+
+    freshnessLifetimeGreaterThan: function(resource, timeMs)
+    {
+        var dateHeader = this.responseHeader(resource, "Date");
+        if (!dateHeader)
+            return false;
+
+        var dateHeaderMs = Date.parse(dateHeader);
+        if (isNaN(dateHeaderMs))
+            return false;
+
+        var freshnessLifetimeMs;
+        var maxAgeMatch = this.responseHeaderMatch(resource, "Cache-Control", "max-age=(\\d+)");
+
+        if (maxAgeMatch)
+            freshnessLifetimeMs = (maxAgeMatch[1]) ? 1000 * maxAgeMatch[1] : 0;
+        else {
+            var expiresHeader = this.responseHeader(resource, "Expires");
+            if (expiresHeader) {
+                var expDate = Date.parse(expiresHeader);
+                if (!isNaN(expDate))
+                    freshnessLifetimeMs = expDate - dateHeaderMs;
+            }
+        }
+
+        return (isNaN(freshnessLifetimeMs)) ? false : freshnessLifetimeMs > timeMs;
+    },
+
+    responseHeader: function(resource, header)
+    {
+        return resource.responseHeaders[header];
+    },
+
+    hasResponseHeader: function(resource, header)
+    {
+        return resource.responseHeaders[header] !== undefined;
+    },
+
+    isCompressible: function(resource)
+    {
+        return WebInspector.Resource.Type.isTextType(resource.type);
+    },
+
+    isPubliclyCacheable: function(resource)
+    {
+        if (this._isExplicitlyNonCacheable(resource))
+            return false;
+
+        if (this.responseHeaderMatch(resource, "Cache-Control", "public"))
+            return true;
+
+        return resource.url.indexOf("?") == -1 && !this.responseHeaderMatch(resource, "Cache-Control", "private");
+    },
+
+    responseHeaderMatch: function(resource, header, regexp)
+    {
+        return resource.responseHeaders[header]
+            ? resource.responseHeaders[header].match(new RegExp(regexp, "im"))
+            : undefined;
+    },
+
+    hasExplicitExpiration: function(resource)
+    {
+        return this.hasResponseHeader(resource, "Date") &&
+            (this.hasResponseHeader(resource, "Expires") || this.responseHeaderMatch(resource, "Cache-Control", "max-age"));
+    },
+
+    _isExplicitlyNonCacheable: function(resource)
+    {
+        var hasExplicitExp = this.hasExplicitExpiration(resource);
+        return this.responseHeaderMatch(resource, "Cache-Control", "(no-cache|no-store|must-revalidate)") ||
+            this.responseHeaderMatch(resource, "Pragma", "no-cache") ||
+            (hasExplicitExp && !this.freshnessLifetimeGreaterThan(resource, 0)) ||
+            (!hasExplicitExp && resource.url && resource.url.indexOf("?") >= 0) ||
+            (!hasExplicitExp && !this.isCacheableResource(resource));
+    },
+
+    isCacheableResource: function(resource)
+    {
+        return resource.statusCode !== undefined && WebInspector.AuditRules.CacheableResponseCodes[resource.statusCode];
+    }
+}
+
+WebInspector.AuditRules.CacheControlRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.BrowserCacheControlRule = function()
+{
+    WebInspector.AuditRules.CacheControlRule.call(this, "http-browsercache", "Leverage browser caching");
+}
+
+WebInspector.AuditRules.BrowserCacheControlRule.prototype = {
+    handleNonCacheableResources: function(resources, result)
+    {
+        if (resources.length) {
+            var entry = result.addChild("The following resources are explicitly non-cacheable. Consider making them cacheable if possible:", true);
+            result.violationCount += resources.length;
+            for (var i = 0; i < resources.length; ++i)
+                entry.addURL(resources[i].url);
+        }
+    },
+
+    runChecks: function(resources, result, callback)
+    {
+        this.execCheck("The following resources are missing a cache expiration. Resources that do not specify an expiration may not be cached by browsers:",
+            this._missingExpirationCheck, resources, result);
+        this.execCheck("The following resources specify a \"Vary\" header that disables caching in most versions of Internet Explorer:",
+            this._varyCheck, resources, result);
+        this.execCheck("The following cacheable resources have a short freshness lifetime:",
+            this._oneMonthExpirationCheck, resources, result);
+
+        // Unable to implement the favicon check due to the WebKit limitations.
+        this.execCheck("To further improve cache hit rate, specify an expiration one year in the future for the following cacheable resources:",
+            this._oneYearExpirationCheck, resources, result);
+    },
+
+    _missingExpirationCheck: function(resource)
+    {
+        return this.isCacheableResource(resource) && !this.hasResponseHeader(resource, "Set-Cookie") && !this.hasExplicitExpiration(resource);
+    },
+
+    _varyCheck: function(resource)
+    {
+        var varyHeader = this.responseHeader(resource, "Vary");
+        if (varyHeader) {
+            varyHeader = varyHeader.replace(/User-Agent/gi, "");
+            varyHeader = varyHeader.replace(/Accept-Encoding/gi, "");
+            varyHeader = varyHeader.replace(/[, ]*/g, "");
+        }
+        return varyHeader && varyHeader.length && this.isCacheableResource(resource) && this.freshnessLifetimeGreaterThan(resource, 0);
+    },
+
+    _oneMonthExpirationCheck: function(resource)
+    {
+        return this.isCacheableResource(resource) &&
+            !this.hasResponseHeader(resource, "Set-Cookie") &&
+            !this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
+            this.freshnessLifetimeGreaterThan(resource, 0);
+    },
+
+    _oneYearExpirationCheck: function(resource)
+    {
+        return this.isCacheableResource(resource) &&
+            !this.hasResponseHeader(resource, "Set-Cookie") &&
+            !this.freshnessLifetimeGreaterThan(resource, 11 * WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
+            this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth);
+    }
+}
+
+WebInspector.AuditRules.BrowserCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;
+
+
+WebInspector.AuditRules.ProxyCacheControlRule = function() {
+    WebInspector.AuditRules.CacheControlRule.call(this, "http-proxycache", "Leverage proxy caching");
+}
+
+WebInspector.AuditRules.ProxyCacheControlRule.prototype = {
+    runChecks: function(resources, result, callback)
+    {
+        this.execCheck("Resources with a \"?\" in the URL are not cached by most proxy caching servers:",
+            this._questionMarkCheck, resources, result);
+        this.execCheck("Consider adding a \"Cache-Control: public\" header to the following resources:",
+            this._publicCachingCheck, resources, result);
+        this.execCheck("The following publicly cacheable resources contain a Set-Cookie header. This security vulnerability can cause cookies to be shared by multiple users.",
+            this._setCookieCacheableCheck, resources, result);
+    },
+
+    _questionMarkCheck: function(resource)
+    {
+        return resource.url.indexOf("?") >= 0 && !this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
+    },
+
+    _publicCachingCheck: function(resource)
+    {
+        return this.isCacheableResource(resource) &&
+            !this.isCompressible(resource) &&
+            !this.responseHeaderMatch(resource, "Cache-Control", "public") &&
+            !this.hasResponseHeader(resource, "Set-Cookie");
+    },
+
+    _setCookieCacheableCheck: function(resource)
+    {
+        return this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
+    }
+}
+
+WebInspector.AuditRules.ProxyCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;
+
+
+WebInspector.AuditRules.ImageDimensionsRule = function()
+{
+    WebInspector.AuditRule.call(this, "page-imagedims", "Specify image dimensions");
+}
+
+WebInspector.AuditRules.ImageDimensionsRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        function doneCallback(context)
+        {
+            var map = context.urlToNoDimensionCount;
+            for (var url in map) {
+                var entry = entry || result.addChild("A width and height should be specified for all images in order to speed up page display. The following image(s) are missing a width and/or height:", true);
+                var value = WebInspector.AuditRuleResult.linkifyDisplayName(url);
+                if (map[url] > 1)
+                    value += String.sprintf(" (%d uses)", map[url]);
+                entry.addChild(value);
+                result.violationCount++;
+            }
+            callback(entry ? result : null);
+        }
+
+        function imageStylesReady(imageId, context, styles)
+        {
+            --context.imagesLeft;
+
+            const node = WebInspector.domAgent.nodeForId(imageId);
+            var src = node.getAttribute("src");
+            if (!src.asParsedURL()) {
+                for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
+                    if (frameOwnerCandidate.documentURL) {
+                        var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src);
+                        break;
+                    }
+                }
+            }
+            if (completeSrc)
+                src = completeSrc;
+
+            const computedStyle = styles.computedStyle;
+            if (computedStyle.getPropertyValue("position") === "absolute") {
+                if (!context.imagesLeft)
+                    doneCallback(context);
+                return;
+            }
+
+            var widthFound = "width" in styles.styleAttributes;
+            var heightFound = "height" in styles.styleAttributes;
+
+            for (var i = styles.matchedCSSRules.length - 1; i >= 0 && !(widthFound && heightFound); --i) {
+                var style = styles.matchedCSSRules[i].style;
+                if (style.getPropertyValue("width") !== "")
+                    widthFound = true;
+                if (style.getPropertyValue("height") !== "")
+                    heightFound = true;
+            }
+            
+            if (!widthFound || !heightFound) {
+                if (src in context.urlToNoDimensionCount)
+                    ++context.urlToNoDimensionCount[src];
+                else
+                    context.urlToNoDimensionCount[src] = 1;
+            }
+
+            if (!context.imagesLeft)
+                doneCallback(context);
+        }
+
+        function receivedImages(imageIds)
+        {
+            if (!imageIds || !imageIds.length)
+                return callback(null);
+            var context = {imagesLeft: imageIds.length, urlToNoDimensionCount: {}};
+            for (var i = imageIds.length - 1; i >= 0; --i)
+                WebInspector.cssModel.getStylesAsync(imageIds[i], imageStylesReady.bind(this, imageIds[i], context));
+        }
+
+        function pushImageNodes()
+        {
+            const nodeIds = [];
+            var nodes = document.getElementsByTagName("img");
+            for (var i = 0; i < nodes.length; ++i) {
+                if (!nodes[i].src)
+                    continue;
+                var nodeId = this.getNodeId(nodes[i]);
+                nodeIds.push(nodeId);
+            }
+            return nodeIds;
+        }
+
+        WebInspector.AuditRules.evaluateInTargetWindow(pushImageNodes, [], receivedImages);
+    }
+}
+
+WebInspector.AuditRules.ImageDimensionsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CssInHeadRule = function()
+{
+    WebInspector.AuditRule.call(this, "page-cssinhead", "Put CSS in the document head");
+}
+
+WebInspector.AuditRules.CssInHeadRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        function evalCallback(evalResult)
+        {
+            if (!evalResult)
+                return callback(null);
+
+            var summary = result.addChild("");
+
+            var outputMessages = [];
+            for (var url in evalResult) {
+                var urlViolations = evalResult[url];
+                if (urlViolations[0]) {
+                    result.addChild(String.sprintf("%s style block(s) in the %s body should be moved to the document head.", urlViolations[0], WebInspector.AuditRuleResult.linkifyDisplayName(url)));
+                    result.violationCount += urlViolations[0];
+                }
+                for (var i = 0; i < urlViolations[1].length; ++i)
+                    result.addChild(String.sprintf("Link node %s should be moved to the document head in %s", WebInspector.AuditRuleResult.linkifyDisplayName(urlViolations[1][i]), WebInspector.AuditRuleResult.linkifyDisplayName(url)));
+                result.violationCount += urlViolations[1].length;
+            }
+            summary.value = String.sprintf("CSS in the document body adversely impacts rendering performance.");
+            callback(result);
+        }
+
+        function routine()
+        {
+            function allViews() {
+                var views = [document.defaultView];
+                var curView = 0;
+                while (curView < views.length) {
+                    var view = views[curView];
+                    var frames = view.frames;
+                    for (var i = 0; i < frames.length; ++i) {
+                        if (frames[i] !== view)
+                            views.push(frames[i]);
+                    }
+                    ++curView;
+                }
+                return views;
+            }
+
+            var views = allViews();
+            var urlToViolationsArray = {};
+            var found = false;
+            for (var i = 0; i < views.length; ++i) {
+                var view = views[i];
+                if (!view.document)
+                    continue;
+
+                var inlineStyles = view.document.querySelectorAll("body style");
+                var inlineStylesheets = view.document.querySelectorAll("body link[rel~='stylesheet'][href]");
+                if (!inlineStyles.length && !inlineStylesheets.length)
+                    continue;
+
+                found = true;
+                var inlineStylesheetHrefs = [];
+                for (var j = 0; j < inlineStylesheets.length; ++j)
+                    inlineStylesheetHrefs.push(inlineStylesheets[j].href);
+                urlToViolationsArray[view.location.href] = [inlineStyles.length, inlineStylesheetHrefs];
+            }
+            return found ? urlToViolationsArray : null;
+        }
+
+        WebInspector.AuditRules.evaluateInTargetWindow(routine, [], evalCallback);
+    }
+}
+
+WebInspector.AuditRules.CssInHeadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.StylesScriptsOrderRule = function()
+{
+    WebInspector.AuditRule.call(this, "page-stylescriptorder", "Optimize the order of styles and scripts");
+}
+
+WebInspector.AuditRules.StylesScriptsOrderRule.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        function evalCallback(resultValue)
+        {
+            if (!resultValue)
+                return callback(null);
+
+            var lateCssUrls = resultValue[0];
+            var cssBeforeInlineCount = resultValue[1];
+
+            var entry = result.addChild("The following external CSS files were included after an external JavaScript file in the document head. To ensure CSS files are downloaded in parallel, always include external CSS before external JavaScript.", true);
+            entry.addURLs(lateCssUrls);
+            result.violationCount += lateCssUrls.length;
+
+            if (cssBeforeInlineCount) {
+                result.addChild(String.sprintf(" %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline script before the external CSS file, or after the next resource.", cssBeforeInlineCount, cssBeforeInlineCount > 1 ? "s were" : " was"));
+                result.violationCount += cssBeforeInlineCount;
+            }
+            callback(result);
+        }
+
+        function routine()
+        {
+            var lateStyles = document.querySelectorAll("head script[src] ~ link[rel~='stylesheet'][href]");
+            var cssBeforeInlineCount = document.querySelectorAll("head link[rel~='stylesheet'][href] ~ script:not([src])").length;
+            if (!lateStyles.length && !cssBeforeInlineCount)
+                return null;
+
+            var lateStyleUrls = [];
+            for (var i = 0; i < lateStyles.length; ++i)
+                lateStyleUrls.push(lateStyles[i].href);
+            return [ lateStyleUrls, cssBeforeInlineCount ];
+        }
+
+        WebInspector.AuditRules.evaluateInTargetWindow(routine, [], evalCallback.bind(this));
+    }
+}
+
+WebInspector.AuditRules.StylesScriptsOrderRule.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CookieRuleBase = function(id, name)
+{
+    WebInspector.AuditRule.call(this, id, name);
+}
+
+WebInspector.AuditRules.CookieRuleBase.prototype = {
+    doRun: function(resources, result, callback)
+    {
+        var self = this;
+        function resultCallback(receivedCookies, isAdvanced) {
+            self.processCookies(isAdvanced ? receivedCookies : [], resources, result);
+            callback(result);
+        }
+        WebInspector.Cookies.getCookiesAsync(resultCallback);
+    },
+
+    mapResourceCookies: function(resourcesByDomain, allCookies, callback)
+    {
+        for (var i = 0; i < allCookies.length; ++i) {
+            for (var resourceDomain in resourcesByDomain) {
+                if (WebInspector.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain, resourceDomain))
+                    this._callbackForResourceCookiePairs(resourcesByDomain[resourceDomain], allCookies[i], callback);
+            }
+        }
+    },
+
+    _callbackForResourceCookiePairs: function(resources, cookie, callback)
+    {
+        if (!resources)
+            return;
+        for (var i = 0; i < resources.length; ++i) {
+            if (WebInspector.Cookies.cookieMatchesResourceURL(cookie, resources[i].url))
+                callback(resources[i], cookie);
+        }
+    }
+}
+
+WebInspector.AuditRules.CookieRuleBase.prototype.__proto__ = WebInspector.AuditRule.prototype;
+
+
+WebInspector.AuditRules.CookieSizeRule = function(avgBytesThreshold)
+{
+    WebInspector.AuditRules.CookieRuleBase.call(this, "http-cookiesize", "Minimize cookie size");
+    this._avgBytesThreshold = avgBytesThreshold;
+    this._maxBytesThreshold = 1000;
+}
+
+WebInspector.AuditRules.CookieSizeRule.prototype = {
+    _average: function(cookieArray)
+    {
+        var total = 0;
+        for (var i = 0; i < cookieArray.length; ++i)
+            total += cookieArray[i].size;
+        return cookieArray.length ? Math.round(total / cookieArray.length) : 0;
+    },
+
+    _max: function(cookieArray)
+    {
+        var result = 0;
+        for (var i = 0; i < cookieArray.length; ++i)
+            result = Math.max(cookieArray[i].size, result);
+        return result;
+    },
+
+    processCookies: function(allCookies, resources, result)
+    {
+        function maxSizeSorter(a, b)
+        {
+            return b.maxCookieSize - a.maxCookieSize;
+        }
+
+        function avgSizeSorter(a, b)
+        {
+            return b.avgCookieSize - a.avgCookieSize;
+        }
+
+        var cookiesPerResourceDomain = {};
+
+        function collectorCallback(resource, cookie)
+        {
+            var cookies = cookiesPerResourceDomain[resource.domain];
+            if (!cookies) {
+                cookies = [];
+                cookiesPerResourceDomain[resource.domain] = cookies;
+            }
+            cookies.push(cookie);
+        }
+
+        if (!allCookies.length)
+            return;
+
+        var sortedCookieSizes = [];
+
+        var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
+                null,
+                true);
+        var matchingResourceData = {};
+        this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this));
+
+        for (var resourceDomain in cookiesPerResourceDomain) {
+            var cookies = cookiesPerResourceDomain[resourceDomain];
+            sortedCookieSizes.push({
+                domain: resourceDomain,
+                avgCookieSize: this._average(cookies),
+                maxCookieSize: this._max(cookies)
+            });
+        }
+        var avgAllCookiesSize = this._average(allCookies);
+
+        var hugeCookieDomains = [];
+        sortedCookieSizes.sort(maxSizeSorter);
+
+        for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
+            var maxCookieSize = sortedCookieSizes[i].maxCookieSize;
+            if (maxCookieSize > this._maxBytesThreshold)
+                hugeCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ": " + Number.bytesToString(maxCookieSize));
+        }
+
+        var bigAvgCookieDomains = [];
+        sortedCookieSizes.sort(avgSizeSorter);
+        for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
+            var domain = sortedCookieSizes[i].domain;
+            var avgCookieSize = sortedCookieSizes[i].avgCookieSize;
+            if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBytesThreshold)
+                bigAvgCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(domain) + ": " + Number.bytesToString(avgCookieSize));
+        }
+        result.addChild(String.sprintf("The average cookie size for all requests on this page is %s", Number.bytesToString(avgAllCookiesSize)));
+
+        var message;
+        if (hugeCookieDomains.length) {
+            var entry = result.addChild("The following domains have a cookie size in excess of 1KB. This is harmful because requests with cookies larger than 1KB typically cannot fit into a single network packet.", true);
+            entry.addURLs(hugeCookieDomains);
+            result.violationCount += hugeCookieDomains.length;
+        }
+
+        if (bigAvgCookieDomains.length) {
+            var entry = result.addChild(String.sprintf("The following domains have an average cookie size in excess of %d bytes. Reducing the size of cookies for these domains can reduce the time it takes to send requests.", this._avgBytesThreshold), true);
+            entry.addURLs(bigAvgCookieDomains);
+            result.violationCount += bigAvgCookieDomains.length;
+        }
+    }
+}
+
+WebInspector.AuditRules.CookieSizeRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;
+
+
+WebInspector.AuditRules.StaticCookielessRule = function(minResources)
+{
+    WebInspector.AuditRules.CookieRuleBase.call(this, "http-staticcookieless", "Serve static content from a cookieless domain");
+    this._minResources = minResources;
+}
+
+WebInspector.AuditRules.StaticCookielessRule.prototype = {
+    processCookies: function(allCookies, resources, result)
+    {
+        var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
+                [WebInspector.Resource.Type.Stylesheet,
+                 WebInspector.Resource.Type.Image],
+                true);
+        var totalStaticResources = 0;
+        for (var domain in domainToResourcesMap)
+            totalStaticResources += domainToResourcesMap[domain].length;
+        if (totalStaticResources < this._minResources)
+            return;
+        var matchingResourceData = {};
+        this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCallback.bind(this, matchingResourceData));
+
+        var badUrls = [];
+        var cookieBytes = 0;
+        for (var url in matchingResourceData) {
+            badUrls.push(url);
+            cookieBytes += matchingResourceData[url]
+        }
+        if (badUrls.length < this._minResources)
+            return;
+
+        var entry = result.addChild(String.sprintf("%s of cookies were sent with the following static resources. Serve these static resources from a domain that does not set cookies:", Number.bytesToString(cookieBytes)), true);
+        entry.addURLs(badUrls);
+        result.violationCount = badUrls.length;
+    },
+
+    _collectorCallback: function(matchingResourceData, resource, cookie)
+    {
+        matchingResourceData[resource.url] = (matchingResourceData[resource.url] || 0) + cookie.size;
+    }
+}
+
+WebInspector.AuditRules.StaticCookielessRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditsPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditsPanel.js
new file mode 100644
index 0000000..47c0b30
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/AuditsPanel.js
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.AuditsPanel = function()
+{
+    WebInspector.Panel.call(this, "audits");
+
+    this.createSidebar();
+    this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
+    this.sidebarTree.appendChild(this.auditsTreeElement);
+    this.auditsTreeElement.listItemElement.addStyleClass("hidden");
+    this.auditsTreeElement.expand();
+
+    this.auditsItemTreeElement = new WebInspector.AuditsSidebarTreeElement();
+    this.auditsTreeElement.appendChild(this.auditsItemTreeElement);
+
+    this.auditResultsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESULTS"), {}, true);
+    this.sidebarTree.appendChild(this.auditResultsTreeElement);
+    this.auditResultsTreeElement.expand();
+
+    this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear audit results."), "clear-status-bar-item");
+    this.clearResultsButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
+
+    this.viewsContainerElement = document.createElement("div");
+    this.viewsContainerElement.id = "audit-views";
+    this.element.appendChild(this.viewsContainerElement);
+
+    this._constructCategories();
+
+    this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this));
+    for (id in this.categoriesById)
+        this._launcherView.addCategory(this.categoriesById[id]);
+}
+
+WebInspector.AuditsPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Audits");
+    },
+
+    get statusBarItems()
+    {
+        return [this.clearResultsButton.element];
+    },
+
+    get mainResourceLoadTime()
+    {
+        return this._mainResourceLoadTime;
+    },
+
+    set mainResourceLoadTime(x)
+    {
+        this._mainResourceLoadTime = x;
+        this._didMainResourceLoad();
+    },
+
+    get mainResourceDOMContentTime()
+    {
+        return this._mainResourceDOMContentTime;
+    },
+
+    set mainResourceDOMContentTime(x)
+    {
+        this._mainResourceDOMContentTime = x;
+    },
+
+    get categoriesById()
+    {
+        return this._auditCategoriesById;
+    },
+
+    addCategory: function(category)
+    {
+        this.categoriesById[category.id] = category;
+        this._launcherView.addCategory(category);
+    },
+
+    getCategory: function(id)
+    {
+        return this.categoriesById[id];
+    },
+
+    _constructCategories: function()
+    {
+        this._auditCategoriesById = {};
+        for (var categoryCtorID in WebInspector.AuditCategories) {
+            var auditCategory = new WebInspector.AuditCategories[categoryCtorID]();
+            auditCategory._id = categoryCtorID;
+            this.categoriesById[categoryCtorID] = auditCategory;
+        }
+    },
+
+    _executeAudit: function(categories, resultCallback)
+    {
+        var resources = WebInspector.networkResources;
+
+        var rulesRemaining = 0;
+        for (var i = 0; i < categories.length; ++i)
+            rulesRemaining += categories[i].ruleCount;
+
+        var results = [];
+        var mainResourceURL = WebInspector.mainResource.url;
+
+        function ruleResultReadyCallback(categoryResult, ruleResult)
+        {
+            if (ruleResult && ruleResult.children)
+                categoryResult.addRuleResult(ruleResult);
+
+            --rulesRemaining;
+
+            if (!rulesRemaining && resultCallback)
+                resultCallback(mainResourceURL, results);
+        }
+
+        if (!rulesRemaining) {
+            resultCallback(mainResourceURL, results);
+            return;
+        }
+
+        for (var i = 0; i < categories.length; ++i) {
+            var category = categories[i];
+            var result = new WebInspector.AuditCategoryResult(category);
+            results.push(result);
+            category.run(resources, ruleResultReadyCallback.bind(null, result));
+        }
+    },
+
+    _auditFinishedCallback: function(launcherCallback, mainResourceURL, results)
+    {
+        var children = this.auditResultsTreeElement.children;
+        var ordinal = 1;
+        for (var i = 0; i < children.length; ++i) {
+            if (children[i].mainResourceURL === mainResourceURL)
+                ordinal++;
+        }
+
+        var resultTreeElement = new WebInspector.AuditResultSidebarTreeElement(results, mainResourceURL, ordinal);
+        this.auditResultsTreeElement.appendChild(resultTreeElement);
+        resultTreeElement.reveal();
+        resultTreeElement.select();
+        if (launcherCallback)
+            launcherCallback();
+    },
+
+    initiateAudit: function(categoryIds, runImmediately, launcherCallback)
+    {
+        if (!categoryIds || !categoryIds.length)
+            return;
+
+        var categories = [];
+        for (var i = 0; i < categoryIds.length; ++i)
+            categories.push(this.categoriesById[categoryIds[i]]);
+
+        function initiateAuditCallback(categories, launcherCallback)
+        {
+            this._executeAudit(categories, this._auditFinishedCallback.bind(this, launcherCallback));
+        }
+
+        if (runImmediately)
+            initiateAuditCallback.call(this, categories, launcherCallback);
+        else
+            this._reloadResources(initiateAuditCallback.bind(this, categories, launcherCallback));
+    },
+
+    _reloadResources: function(callback)
+    {
+        this._pageReloadCallback = callback;
+        InspectorBackend.reloadPage(false);
+    },
+
+    _didMainResourceLoad: function()
+    {
+        if (this._pageReloadCallback) {
+            var callback = this._pageReloadCallback;
+            delete this._pageReloadCallback;
+            callback();
+        }
+    },
+
+    showResults: function(categoryResults)
+    {
+        if (!categoryResults._resultView)
+            categoryResults._resultView = new WebInspector.AuditResultView(categoryResults);
+
+        this.visibleView = categoryResults._resultView;
+    },
+
+    showLauncherView: function()
+    {
+        this.visibleView = this._launcherView;
+    },
+
+    get visibleView()
+    {
+        return this._visibleView;
+    },
+
+    set visibleView(x)
+    {
+        if (this._visibleView === x)
+            return;
+
+        if (this._visibleView)
+            this._visibleView.hide();
+
+        this._visibleView = x;
+
+        if (x)
+            x.show(this.viewsContainerElement);
+    },
+
+    attach: function()
+    {
+        WebInspector.Panel.prototype.attach.call(this);
+
+        this.auditsItemTreeElement.select();
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this.viewsContainerElement.style.left = width + "px";
+    },
+
+    _clearButtonClicked: function()
+    {
+        this.auditsItemTreeElement.reveal();
+        this.auditsItemTreeElement.select();
+        this.auditResultsTreeElement.removeChildren();
+    }
+}
+
+WebInspector.AuditsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+
+
+WebInspector.AuditCategory = function(displayName)
+{
+    this._displayName = displayName;
+    this._rules = [];
+}
+
+WebInspector.AuditCategory.prototype = {
+    get id()
+    {
+        // this._id value is injected at construction time.
+        return this._id;
+    },
+
+    get displayName()
+    {
+        return this._displayName;
+    },
+
+    get ruleCount()
+    {
+        this._ensureInitialized();
+        return this._rules.length;
+    },
+
+    addRule: function(rule, severity)
+    {
+        rule.severity = severity;
+        this._rules.push(rule);
+    },
+
+    run: function(resources, callback)
+    {
+        this._ensureInitialized();
+        for (var i = 0; i < this._rules.length; ++i)
+            this._rules[i].run(resources, callback);
+    },
+
+    _ensureInitialized: function()
+    {
+        if (!this._initialized) {
+            if ("initialize" in this)
+                this.initialize();
+            this._initialized = true;
+        }
+    }
+}
+
+
+WebInspector.AuditRule = function(id, displayName)
+{
+    this._id = id;
+    this._displayName = displayName;
+}
+
+WebInspector.AuditRule.Severity = {
+    Info: "info",
+    Warning: "warning",
+    Severe: "severe"
+}
+
+WebInspector.AuditRule.SeverityOrder = {
+    "info": 3,
+    "warning": 2,
+    "severe": 1
+}
+
+WebInspector.AuditRule.prototype = {
+    get id()
+    {
+        return this._id;
+    },
+
+    get displayName()
+    {
+        return this._displayName;
+    },
+
+    set severity(severity)
+    {
+        this._severity = severity;
+    },
+
+    run: function(resources, callback)
+    {
+        var result = new WebInspector.AuditRuleResult(this.displayName);
+        result.severity = this._severity;
+        this.doRun(resources, result, callback);
+    },
+
+    doRun: function(resources, result, callback)
+    {
+        throw new Error("doRun() not implemented");
+    }
+}
+
+WebInspector.AuditCategoryResult = function(category)
+{
+    this.title = category.displayName;
+    this.ruleResults = [];
+}
+
+WebInspector.AuditCategoryResult.prototype = {
+    addRuleResult: function(ruleResult)
+    {
+        this.ruleResults.push(ruleResult);
+    }
+}
+
+WebInspector.AuditRuleResult = function(value, expanded, className)
+{
+    this.value = value;
+    this.className = className;
+    this.expanded = expanded;
+    this.violationCount = 0;
+}
+
+WebInspector.AuditRuleResult.linkifyDisplayName = function(url)
+{
+    return WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url));
+}
+
+WebInspector.AuditRuleResult.resourceDomain = function(domain)
+{
+    return domain || WebInspector.UIString("[empty domain]");
+}
+
+WebInspector.AuditRuleResult.prototype = {
+    addChild: function(value, expanded, className)
+    {
+        if (!this.children)
+            this.children = [];
+        var entry = new WebInspector.AuditRuleResult(value, expanded, className);
+        this.children.push(entry);
+        return entry;
+    },
+
+    addURL: function(url)
+    {
+        return this.addChild(WebInspector.AuditRuleResult.linkifyDisplayName(url));
+    },
+
+    addURLs: function(urls)
+    {
+        for (var i = 0; i < urls.length; ++i)
+            this.addURL(urls[i]);
+    },
+
+    addSnippet: function(snippet)
+    {
+        return this.addChild(snippet, false, "source-code");
+    }
+}
+
+WebInspector.AuditsSidebarTreeElement = function()
+{
+    this.small = false;
+
+    WebInspector.SidebarTreeElement.call(this, "audits-sidebar-tree-item", WebInspector.UIString("Audits"), "", null, false);
+}
+
+WebInspector.AuditsSidebarTreeElement.prototype = {
+    onattach: function()
+    {
+        WebInspector.SidebarTreeElement.prototype.onattach.call(this);
+    },
+
+    onselect: function()
+    {
+        WebInspector.panels.audits.showLauncherView();
+    },
+
+    get selectable()
+    {
+        return true;
+    },
+
+    refresh: function()
+    {
+        this.refreshTitles();
+    }
+}
+
+WebInspector.AuditsSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+
+WebInspector.AuditResultSidebarTreeElement = function(results, mainResourceURL, ordinal)
+{
+    this.results = results;
+    this.mainResourceURL = mainResourceURL;
+
+    WebInspector.SidebarTreeElement.call(this, "audit-result-sidebar-tree-item", String.sprintf("%s (%d)", mainResourceURL, ordinal), "", {}, false);
+}
+
+WebInspector.AuditResultSidebarTreeElement.prototype = {
+    onselect: function()
+    {
+        WebInspector.panels.audits.showResults(this.results);
+    },
+
+    get selectable()
+    {
+        return true;
+    }
+}
+
+WebInspector.AuditResultSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+// Contributed audit rules should go into this namespace.
+WebInspector.AuditRules = {};
+
+// Contributed audit categories should go into this namespace.
+WebInspector.AuditCategories = {};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js
new file mode 100644
index 0000000..5aaae0c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Bottom Up Profiling shows the entire callstack backwards:
+// The root node is a representation of each individual function called, and each child of that node represents
+// a reverse-callstack showing how many of those calls came from it. So, unlike top-down, the statistics in
+// each child still represent the root node. We have to be particularly careful of recursion with this mode
+// because a root node can represent itself AND an ancestor.
+
+WebInspector.BottomUpProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*BottomUpProfileDataGridTree*/ owningTree)
+{
+    WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, this._willHaveChildren(profileNode));
+
+    this._remainingNodeInfos = [];
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype = {
+    _takePropertiesFromProfileDataGridNode: function(/*ProfileDataGridNode*/ profileDataGridNode)
+    {
+        this._save();
+
+        this.selfTime = profileDataGridNode.selfTime;
+        this.totalTime = profileDataGridNode.totalTime;
+        this.numberOfCalls = profileDataGridNode.numberOfCalls;
+    },
+
+    // When focusing, we keep just the members of the callstack.
+    _keepOnlyChild: function(/*ProfileDataGridNode*/ child)
+    {
+        this._save();
+
+        this.removeChildren();
+        this.appendChild(child);
+    },
+
+    _exclude: function(aCallUID)
+    {
+        if (this._remainingNodeInfos)
+            this._populate();
+
+        this._save();
+
+        var children = this.children;
+        var index = this.children.length;
+
+        while (index--)
+            children[index]._exclude(aCallUID);
+
+        var child = this.childrenByCallUID[aCallUID];
+
+        if (child)
+            this._merge(child, true);
+    },
+
+    _restore: function()
+    {
+        WebInspector.ProfileDataGridNode.prototype._restore();
+
+        if (!this.children.length)
+            this.hasChildren = this._willHaveChildren();
+    },
+
+    _merge: function(/*ProfileDataGridNode*/ child, /*Boolean*/ shouldAbsorb)
+    {
+        this.selfTime -= child.selfTime;
+
+        WebInspector.ProfileDataGridNode.prototype._merge.call(this, child, shouldAbsorb);
+    },
+
+    _sharedPopulate: function()
+    {
+        var remainingNodeInfos = this._remainingNodeInfos;
+        var count = remainingNodeInfos.length;
+
+        for (var index = 0; index < count; ++index) {
+            var nodeInfo = remainingNodeInfos[index];
+            var ancestor = nodeInfo.ancestor;
+            var focusNode = nodeInfo.focusNode;
+            var child = this.findChild(ancestor);
+
+            // If we already have this child, then merge the data together.
+            if (child) {
+                var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor;
+
+                child.selfTime += focusNode.selfTime;
+                child.numberOfCalls += focusNode.numberOfCalls;
+
+                if (!totalTimeAccountedFor)
+                    child.totalTime += focusNode.totalTime;
+            } else {
+                // If not, add it as a true ancestor.
+                // In heavy mode, we take our visual identity from ancestor node...
+                var child = new WebInspector.BottomUpProfileDataGridNode(this.profileView, ancestor, this.tree);
+
+                if (ancestor !== focusNode) {
+                    // but the actual statistics from the "root" node (bottom of the callstack).
+                    child.selfTime = focusNode.selfTime;
+                    child.totalTime = focusNode.totalTime;
+                    child.numberOfCalls = focusNode.numberOfCalls;
+                }
+
+                this.appendChild(child);
+            }
+
+            var parent = ancestor.parent;
+            if (parent && parent.parent) {
+                nodeInfo.ancestor = parent;
+                child._remainingNodeInfos.push(nodeInfo);
+            }
+        }
+
+        delete this._remainingNodeInfos;
+    },
+
+    _willHaveChildren: function(profileNode)
+    {
+        profileNode = profileNode || this.profileNode;
+        // In bottom up mode, our parents are our children since we display an inverted tree.
+        // However, we don't want to show the very top parent since it is redundant.
+        return !!(profileNode.parent && profileNode.parent.parent);
+    }
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
+
+WebInspector.BottomUpProfileDataGridTree = function(/*ProfileView*/ aProfileView, /*ProfileNode*/ aProfileNode)
+{
+    WebInspector.ProfileDataGridTree.call(this, aProfileView, aProfileNode);
+
+    // Iterate each node in pre-order.
+    var profileNodeUIDs = 0;
+    var profileNodeGroups = [[], [aProfileNode]];
+    var visitedProfileNodesForCallUID = {};
+
+    this._remainingNodeInfos = [];
+
+    for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) {
+        var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex];
+        var profileNodes = profileNodeGroups[++profileNodeGroupIndex];
+        var count = profileNodes.length;
+
+        for (var index = 0; index < count; ++index) {
+            var profileNode = profileNodes[index];
+
+            if (!profileNode.UID)
+                profileNode.UID = ++profileNodeUIDs;
+
+            if (profileNode.head && profileNode !== profileNode.head) {
+                // The total time of this ancestor is accounted for if we're in any form of recursive cycle.
+                var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID];
+                var totalTimeAccountedFor = false;
+
+                if (!visitedNodes) {
+                    visitedNodes = {}
+                    visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes;
+                } else {
+                    // The total time for this node has already been accounted for iff one of it's parents has already been visited.
+                    // We can do this check in this style because we are traversing the tree in pre-order.
+                    var parentCount = parentProfileNodes.length;
+                    for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) {
+                        if (visitedNodes[parentProfileNodes[parentIndex].UID]) {
+                            totalTimeAccountedFor = true;
+                            break;
+                        }
+                    }
+                }
+
+                visitedNodes[profileNode.UID] = true;
+
+                this._remainingNodeInfos.push({ ancestor:profileNode, focusNode:profileNode, totalTimeAccountedFor:totalTimeAccountedFor });
+            }
+
+            var children = profileNode.children;
+            if (children.length) {
+                profileNodeGroups.push(parentProfileNodes.concat([profileNode]))
+                profileNodeGroups.push(children);
+            }
+        }
+    }
+
+    // Populate the top level nodes.
+    WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(this);
+
+    return this;
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype = {
+    // When focusing, we keep the entire callstack up to this ancestor.
+    focus: function(/*ProfileDataGridNode*/ profileDataGridNode)
+    {
+        if (!profileDataGridNode)
+            return;
+
+        this._save();
+
+        var currentNode = profileDataGridNode;
+        var focusNode = profileDataGridNode;
+
+        while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) {
+            currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode);
+
+            focusNode = currentNode;
+            currentNode = currentNode.parent;
+
+            if (currentNode instanceof WebInspector.ProfileDataGridNode)
+                currentNode._keepOnlyChild(focusNode);
+        }
+
+        this.children = [focusNode];
+        this.totalTime = profileDataGridNode.totalTime;
+    },
+
+    exclude: function(/*ProfileDataGridNode*/ profileDataGridNode)
+    {
+        if (!profileDataGridNode)
+            return;
+
+        this._save();
+
+        var excludedCallUID = profileDataGridNode.callUID;
+        var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID];
+
+        // If we have a top level node that is excluded, get rid of it completely (not keeping children),
+        // since bottom up data relies entirely on the root node.
+        if (excludedTopLevelChild)
+            this.children.remove(excludedTopLevelChild);
+
+        var children = this.children;
+        var count = children.length;
+
+        for (var index = 0; index < count; ++index)
+            children[index]._exclude(excludedCallUID);
+
+        if (this.lastComparator)
+            this.sort(this.lastComparator, true);
+    },
+
+    _sharedPopulate: WebInspector.BottomUpProfileDataGridNode.prototype._sharedPopulate
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
+
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Breakpoint.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Breakpoint.js
new file mode 100644
index 0000000..ebc6029
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Breakpoint.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Breakpoint = function(id, url, sourceID, lineNumber, columnNumber, condition, enabled)
+{
+    this.id = id;
+    this.url = url;
+    this.sourceID = sourceID;
+    this.lineNumber = lineNumber;
+    this.columnNumber = columnNumber;
+    this.condition = condition;
+    this.enabled = enabled;
+    this.locations = [];
+}
+
+WebInspector.Breakpoint.prototype = {
+    addLocation: function(sourceID, lineNumber, columnNumber)
+    {
+        this.locations.push({ sourceID: sourceID, lineNumber: lineNumber, columnNumber: columnNumber });
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointManager.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointManager.js
new file mode 100644
index 0000000..94345d5
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointManager.js
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.BreakpointManager = function()
+{
+    this._stickyBreakpoints = {};
+    var breakpoints = WebInspector.settings.findSettingForAllProjects("nativeBreakpoints");
+    for (var projectId in breakpoints)
+        this._stickyBreakpoints[projectId] = this._validateBreakpoints(breakpoints[projectId]);
+
+    this._breakpoints = {};
+    this._domBreakpointsRestored = false;
+
+    WebInspector.settings.addEventListener(WebInspector.Settings.Events.ProjectChanged, this._projectChanged, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+}
+
+WebInspector.BreakpointManager.BreakpointTypes = {
+    DOM: "DOM",
+    EventListener: "EventListener",
+    XHR: "XHR"
+}
+
+WebInspector.BreakpointManager.Events = {
+    DOMBreakpointAdded: "dom-breakpoint-added",
+    EventListenerBreakpointAdded: "event-listener-breakpoint-added",
+    XHRBreakpointAdded: "xhr-breakpoint-added",
+    ProjectChanged: "project-changed"
+}
+
+WebInspector.BreakpointManager.prototype = {
+    createDOMBreakpoint: function(nodeId, type)
+    {
+        this._createDOMBreakpoint(nodeId, type, true, false);
+    },
+
+    _createDOMBreakpoint: function(nodeId, type, enabled, restored)
+    {
+        var node = WebInspector.domAgent.nodeForId(nodeId);
+        if (!node)
+            return;
+
+        var breakpointId = this._createDOMBreakpointId(nodeId, type);
+        if (breakpointId in this._breakpoints)
+            return;
+
+        var breakpoint = new WebInspector.DOMBreakpoint(node, type);
+        this._setBreakpoint(breakpointId, breakpoint, enabled, restored);
+        if (enabled && restored)
+            breakpoint._enable();
+
+        breakpoint.view = new WebInspector.DOMBreakpointView(this, breakpointId, enabled, node, type);
+        this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.DOMBreakpointAdded, breakpoint.view);
+    },
+
+    createEventListenerBreakpoint: function(eventName)
+    {
+        this._createEventListenerBreakpoint(eventName, true, false);
+    },
+
+    _createEventListenerBreakpoint: function(eventName, enabled, restored)
+    {
+        var breakpointId = this._createEventListenerBreakpointId(eventName);
+        if (breakpointId in this._breakpoints)
+            return;
+
+        var breakpoint = new WebInspector.EventListenerBreakpoint(eventName);
+        this._setBreakpoint(breakpointId, breakpoint, enabled, restored);
+
+        breakpoint.view = new WebInspector.EventListenerBreakpointView(this, breakpointId, enabled, eventName);
+        this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.EventListenerBreakpointAdded, breakpoint.view);
+    },
+
+    createXHRBreakpoint: function(url)
+    {
+        this._createXHRBreakpoint(url, true, false);
+    },
+
+    _createXHRBreakpoint: function(url, enabled, restored)
+    {
+        var breakpointId = this._createXHRBreakpointId(url);
+        if (breakpointId in this._breakpoints)
+            return;
+
+        var breakpoint = new WebInspector.XHRBreakpoint(url);
+        this._setBreakpoint(breakpointId, breakpoint, enabled, restored);
+
+        breakpoint.view = new WebInspector.XHRBreakpointView(this, breakpointId, enabled, url);
+        this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.XHRBreakpointAdded, breakpoint.view);
+    },
+
+    _setBreakpoint: function(breakpointId, breakpoint, enabled, restored)
+    {
+        this._breakpoints[breakpointId] = breakpoint;
+        breakpoint.enabled = enabled;
+        if (restored)
+            return;
+        if (enabled)
+            breakpoint._enable();
+        this._saveBreakpoints();
+    },
+
+    _setBreakpointEnabled: function(breakpointId, enabled)
+    {
+        var breakpoint = this._breakpoints[breakpointId];
+        if (breakpoint.enabled === enabled)
+            return;
+        if (enabled)
+            breakpoint._enable();
+        else
+            breakpoint._disable();
+        breakpoint.enabled = enabled;
+        this._saveBreakpoints();
+    },
+
+    _removeBreakpoint: function(breakpointId)
+    {
+        var breakpoint = this._breakpoints[breakpointId];
+        if (breakpoint.enabled)
+            breakpoint._disable();
+        delete this._breakpoints[breakpointId];
+        this._saveBreakpoints();
+    },
+
+    breakpointViewForEventData: function(eventData)
+    {
+        var breakpointId;
+        if (eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.DOM)
+            breakpointId = this._createDOMBreakpointId(eventData.nodeId, eventData.type);
+        else if (eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.EventListener)
+            breakpointId = this._createEventListenerBreakpointId(eventData.eventName);
+        else if (eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.XHR)
+            breakpointId = this._createXHRBreakpointId(eventData.breakpointURL);
+        else
+            return;
+
+        var breakpoint = this._breakpoints[breakpointId];
+        if (breakpoint)
+            return breakpoint.view;
+    },
+
+    _debuggerPaused: function(event)
+    {
+        var eventType = event.data.eventType;
+        var eventData = event.data.eventData;
+
+        if (eventType !== WebInspector.DebuggerEventTypes.NativeBreakpoint)
+            return;
+
+        var breakpointView = this.breakpointViewForEventData(eventData);
+        if (!breakpointView)
+            return;
+
+        breakpointView.hit = true;
+        this._lastHitBreakpointView = breakpointView;
+    },
+
+    _debuggerResumed: function(event)
+    {
+        if (!this._lastHitBreakpointView)
+            return;
+        this._lastHitBreakpointView.hit = false;
+        delete this._lastHitBreakpointView;
+    },
+
+    _projectChanged: function(event)
+    {
+        this._breakpoints = {};
+        this._domBreakpointsRestored = false;
+        this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.ProjectChanged);
+
+        var breakpoints = this._stickyBreakpoints[WebInspector.settings.projectId] || [];
+        for (var i = 0; i < breakpoints.length; ++i) {
+            var breakpoint = breakpoints[i];
+            if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.EventListener)
+                this._createEventListenerBreakpoint(breakpoint.condition.eventName, breakpoint.enabled, true);
+            else if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.XHR)
+                this._createXHRBreakpoint(breakpoint.condition.url, breakpoint.enabled, true);
+        }
+
+        if (!this._breakpointsPushedToFrontend) {
+            InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+            this._breakpointsPushedToFrontend = true;
+        }
+    },
+
+    restoreDOMBreakpoints: function()
+    {
+        function didPushNodeByPathToFrontend(path, nodeId)
+        {
+            pathToNodeId[path] = nodeId;
+            pendingCalls -= 1;
+            if (pendingCalls)
+                return;
+            for (var i = 0; i < breakpoints.length; ++i) {
+                var breakpoint = breakpoints[i];
+                if (breakpoint.type !== WebInspector.BreakpointManager.BreakpointTypes.DOM)
+                    continue;
+                var nodeId = pathToNodeId[breakpoint.condition.path];
+                if (nodeId)
+                    this._createDOMBreakpoint(nodeId, breakpoint.condition.type, breakpoint.enabled, true);
+            }
+            this._domBreakpointsRestored = true;
+            this._saveBreakpoints();
+        }
+
+        var breakpoints = this._stickyBreakpoints[WebInspector.settings.projectId] || [];
+        var pathToNodeId = {};
+        var pendingCalls = 0;
+        for (var i = 0; i < breakpoints.length; ++i) {
+            if (breakpoints[i].type !== WebInspector.BreakpointManager.BreakpointTypes.DOM)
+                continue;
+            var path = breakpoints[i].condition.path;
+            if (path in pathToNodeId)
+                continue;
+            pathToNodeId[path] = 0;
+            pendingCalls += 1;
+            InspectorBackend.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
+        }
+        if (!pendingCalls)
+            this._domBreakpointsRestored = true;
+    },
+
+    _saveBreakpoints: function()
+    {
+        var breakpoints = [];
+        for (var breakpointId in this._breakpoints) {
+            var breakpoint = this._breakpoints[breakpointId];
+            var persistentBreakpoint = breakpoint._serializeToJSON();
+            persistentBreakpoint.enabled = breakpoint.enabled;
+            breakpoints.push(persistentBreakpoint);
+        }
+        if (!this._domBreakpointsRestored) {
+            var stickyBreakpoints = this._stickyBreakpoints[WebInspector.settings.projectId] || [];
+            for (var i = 0; i < stickyBreakpoints.length; ++i) {
+                if (stickyBreakpoints[i].type === WebInspector.BreakpointManager.BreakpointTypes.DOM)
+                    breakpoints.push(stickyBreakpoints[i]);
+            }
+        }
+        WebInspector.settings.nativeBreakpoints = breakpoints;
+
+        this._stickyBreakpoints[WebInspector.settings.projectId] = breakpoints;
+        InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+    },
+
+    _validateBreakpoints: function(persistentBreakpoints)
+    {
+        var breakpoints = [];
+        var breakpointsSet = {};
+        for (var i = 0; i < persistentBreakpoints.length; ++i) {
+            var breakpoint = persistentBreakpoints[i];
+            if (!("type" in breakpoint && "enabled" in breakpoint && "condition" in breakpoint))
+                continue;
+            var id = breakpoint.type + ":";
+            var condition = breakpoint.condition;
+            if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.DOM) {
+                if (typeof condition.path !== "string" || typeof condition.type !== "number")
+                    continue;
+                id += condition.path + ":" + condition.type;
+            } else if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.EventListener) {
+                if (typeof condition.eventName !== "string")
+                    continue;
+                id += condition.eventName;
+            } else if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.XHR) {
+                if (typeof condition.url !== "string")
+                    continue;
+                id += condition.url;
+            } else
+                continue;
+            if (id in breakpointsSet)
+                continue;
+            breakpointsSet[id] = true;
+            breakpoints.push(breakpoint);
+        }
+        return breakpoints;
+    },
+
+    _createDOMBreakpointId: function(nodeId, type)
+    {
+        return "dom:" + nodeId + ":" + type;
+    },
+
+    _createEventListenerBreakpointId: function(eventName)
+    {
+        return "eventListner:" + eventName;
+    },
+
+    _createXHRBreakpointId: function(url)
+    {
+        return "xhr:" + url;
+    }
+}
+
+WebInspector.BreakpointManager.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DOMBreakpoint = function(node, type)
+{
+    this._nodeId = node.id;
+    this._path = node.path();
+    this._type = type;
+}
+
+WebInspector.DOMBreakpoint.prototype = {
+    _enable: function()
+    {
+        InspectorBackend.setDOMBreakpoint(this._nodeId, this._type);
+    },
+
+    _disable: function()
+    {
+        InspectorBackend.removeDOMBreakpoint(this._nodeId, this._type);
+    },
+
+    _serializeToJSON: function()
+    {
+        var type = WebInspector.BreakpointManager.BreakpointTypes.DOM;
+        return { type: type, condition: { path: this._path, type: this._type } };
+    }
+}
+
+WebInspector.EventListenerBreakpoint = function(eventName)
+{
+    this._eventName = eventName;
+}
+
+WebInspector.EventListenerBreakpoint.prototype = {
+    _enable: function()
+    {
+        InspectorBackend.setEventListenerBreakpoint(this._eventName);
+    },
+
+    _disable: function()
+    {
+        InspectorBackend.removeEventListenerBreakpoint(this._eventName);
+    },
+
+    _serializeToJSON: function()
+    {
+        var type = WebInspector.BreakpointManager.BreakpointTypes.EventListener;
+        return { type: type, condition: { eventName: this._eventName } };
+    }
+}
+
+WebInspector.XHRBreakpoint = function(url)
+{
+    this._url = url;
+}
+
+WebInspector.XHRBreakpoint.prototype = {
+    _enable: function()
+    {
+        InspectorBackend.setXHRBreakpoint(this._url);
+    },
+
+    _disable: function()
+    {
+        InspectorBackend.removeXHRBreakpoint(this._url);
+    },
+
+    _serializeToJSON: function()
+    {
+        var type = WebInspector.BreakpointManager.BreakpointTypes.XHR;
+        return { type: type, condition: { url: this._url } };
+    }
+}
+
+
+
+WebInspector.NativeBreakpointView = function(manager, id, enabled)
+{
+    this._manager = manager;
+    this._id = id;
+    this._enabled = enabled;
+    this._hit = false;
+}
+
+WebInspector.NativeBreakpointView.prototype = {
+    get enabled()
+    {
+        return this._enabled;
+    },
+
+    set enabled(enabled)
+    {
+        this._manager._setBreakpointEnabled(this._id, enabled);
+        this._enabled = enabled;
+        this.dispatchEventToListeners("enable-changed");
+    },
+
+    get hit()
+    {
+        return this._hit;
+    },
+
+    set hit(hit)
+    {
+        this._hit = hit;
+        this.dispatchEventToListeners("hit-state-changed");
+    },
+
+    remove: function()
+    {
+        this._manager._removeBreakpoint(this._id);
+        this._onRemove();
+        this.dispatchEventToListeners("removed");
+    },
+
+    _compare: function(x, y)
+    {
+        if (x !== y)
+            return x < y ? -1 : 1;
+        return 0;
+    },
+
+    _onRemove: function()
+    {
+    }
+}
+
+WebInspector.NativeBreakpointView.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DOMBreakpointView = function(manager, id, enabled, node, type)
+{
+    WebInspector.NativeBreakpointView.call(this, manager, id, enabled);
+    this._node = node;
+    this._nodeId = node.id;
+    this._type = type;
+    node.breakpoints[this._type] = this;
+}
+
+WebInspector.DOMBreakpointView.prototype = {
+    compareTo: function(other)
+    {
+        return this._compare(this._type, other._type);
+    },
+
+    populateLabelElement: function(element)
+    {
+        // FIXME: this should belong to the view, not the manager.
+        var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(this._nodeId);
+        linkifiedNode.addStyleClass("monospace");
+        element.appendChild(linkifiedNode);
+        var description = document.createElement("div");
+        description.className = "source-text";
+        description.textContent = WebInspector.domBreakpointTypeLabel(this._type);
+        element.appendChild(description);
+    },
+
+    populateStatusMessageElement: function(element, eventData)
+    {
+        var substitutions = [WebInspector.domBreakpointTypeLabel(this._type), WebInspector.panels.elements.linkifyNodeById(this._nodeId)];
+        var formatters = {
+            s: function(substitution)
+            {
+                return substitution;
+            }
+        };
+        function append(a, b)
+        {
+            if (typeof b === "string")
+                b = document.createTextNode(b);
+            element.appendChild(b);
+        }
+        if (this._type === WebInspector.DOMBreakpointTypes.SubtreeModified) {
+            var targetNode = WebInspector.panels.elements.linkifyNodeById(eventData.targetNodeId);
+            if (eventData.insertion) {
+                if (eventData.targetNodeId !== this._nodeId)
+                    WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", substitutions.concat(targetNode), formatters, "", append);
+                else
+                    WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.", substitutions, formatters, "", append);
+            } else
+                WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", substitutions.concat(targetNode), formatters, "", append);
+        } else
+            WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s.", substitutions, formatters, "", append);
+    },
+
+    _onRemove: function()
+    {
+        delete this._node.breakpoints[this._type];
+    }
+}
+
+WebInspector.DOMBreakpointView.prototype.__proto__ = WebInspector.NativeBreakpointView.prototype;
+
+WebInspector.EventListenerBreakpointView = function(manager, id, enabled, eventName)
+{
+    WebInspector.NativeBreakpointView.call(this, manager, id, enabled);
+    this._eventName = eventName;
+}
+
+WebInspector.EventListenerBreakpointView.eventNameForUI = function(eventName)
+{
+    if (!WebInspector.EventListenerBreakpointView._eventNamesForUI) {
+        WebInspector.EventListenerBreakpointView._eventNamesForUI = {
+            "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
+            "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
+            "instrumentation:timerFired": WebInspector.UIString("Timer Fired")
+        };
+    }
+    return WebInspector.EventListenerBreakpointView._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
+}
+
+WebInspector.EventListenerBreakpointView.prototype = {
+    get eventName()
+    {
+        return this._eventName;
+    },
+
+    compareTo: function(other)
+    {
+        return this._compare(this._eventName, other._eventName);
+    },
+
+    populateLabelElement: function(element)
+    {
+        element.appendChild(document.createTextNode(this._uiEventName()));
+    },
+
+    populateStatusMessageElement: function(element, eventData)
+    {
+        var status = WebInspector.UIString("Paused on a \"%s\" Event Listener.", this._uiEventName());
+        element.appendChild(document.createTextNode(status));
+    },
+
+    _uiEventName: function()
+    {
+        return WebInspector.EventListenerBreakpointView.eventNameForUI(this._eventName);
+    }
+}
+
+WebInspector.EventListenerBreakpointView.prototype.__proto__ = WebInspector.NativeBreakpointView.prototype;
+
+WebInspector.XHRBreakpointView = function(manager, id, enabled, url)
+{
+    WebInspector.NativeBreakpointView.call(this, manager, id, enabled);
+    this._url = url;
+}
+
+WebInspector.XHRBreakpointView.prototype = {
+    compareTo: function(other)
+    {
+        return this._compare(this._url, other._url);
+    },
+
+    populateEditElement: function(element)
+    {
+        element.textContent = this._url;
+    },
+
+    populateLabelElement: function(element)
+    {
+        var label;
+        if (!this._url.length)
+            label = WebInspector.UIString("Any XHR");
+        else
+            label = WebInspector.UIString("URL contains \"%s\"", this._url);
+        element.appendChild(document.createTextNode(label));
+        element.addStyleClass("cursor-auto");
+    },
+
+    populateStatusMessageElement: function(element)
+    {
+        var status = WebInspector.UIString("Paused on a XMLHttpRequest.");
+        element.appendChild(document.createTextNode(status));
+    }
+}
+
+WebInspector.XHRBreakpointView.prototype.__proto__ = WebInspector.NativeBreakpointView.prototype;
+
+WebInspector.DOMBreakpointTypes = {
+    SubtreeModified: 0,
+    AttributeModified: 1,
+    NodeRemoved: 2
+};
+
+WebInspector.domBreakpointTypeLabel = function(type)
+{
+    if (!WebInspector._DOMBreakpointTypeLabels) {
+        WebInspector._DOMBreakpointTypeLabels = {};
+        WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified");
+        WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified");
+        WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed");
+    }
+    return WebInspector._DOMBreakpointTypeLabels[type];
+}
+
+WebInspector.domBreakpointTypeContextMenuLabel = function(type)
+{
+    if (!WebInspector._DOMBreakpointTypeContextMenuLabels) {
+        WebInspector._DOMBreakpointTypeContextMenuLabels = {};
+        WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications");
+        WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications");
+        WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Break on Node Removal");
+    }
+    return WebInspector._DOMBreakpointTypeContextMenuLabels[type];
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointsSidebarPane.js
new file mode 100644
index 0000000..0c46463
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -0,0 +1,623 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.JavaScriptBreakpointsSidebarPane = function(title)
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
+
+    this.listElement = document.createElement("ol");
+    this.listElement.className = "breakpoint-list";
+
+    this.emptyElement = document.createElement("div");
+    this.emptyElement.className = "info";
+    this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
+
+    this.bodyElement.appendChild(this.emptyElement);
+
+    this._items = {};
+
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+    WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
+}
+
+WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
+    _breakpointAdded: function(event)
+    {
+        var breakpoint = event.data;
+        var breakpointId = breakpoint.id;
+
+        if (breakpoint.url && !WebInspector.debuggerModel.scriptsForURL(breakpoint.url).length)
+            return;
+
+        var element = document.createElement("li");
+
+        var checkbox = document.createElement("input");
+        checkbox.className = "checkbox-elem";
+        checkbox.type = "checkbox";
+        checkbox.checked = breakpoint.enabled;
+        checkbox.addEventListener("click", this._breakpointItemCheckboxClicked.bind(this, breakpointId), false);
+        element.appendChild(checkbox);
+
+        var label = document.createElement("span");
+        element.appendChild(label);
+
+        element._data = breakpoint;
+        var currentElement = this.listElement.firstChild;
+        while (currentElement) {
+            if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
+                break;
+            currentElement = currentElement.nextSibling;
+        }
+        this._addListElement(element, currentElement);
+
+        element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this, breakpointId), true);
+
+        this._setupBreakpointElement(breakpoint, element);
+
+        var breakpointItem = {};
+        breakpointItem.element = element;
+        breakpointItem.checkbox = checkbox;
+        this._items[breakpointId] = breakpointItem;
+
+        if (!this.expanded)
+            this.expanded = true;
+    },
+
+    _breakpointRemoved: function(event)
+    {
+        var breakpointId = event.data;
+        var breakpointItem = this._items[breakpointId];
+        if (breakpointItem) {
+            delete this._items[breakpointId];
+            this._removeListElement(breakpointItem.element);
+        }
+    },
+
+    _breakpointResolved: function(event)
+    {
+        var breakpoint = event.data;
+        this._breakpointRemoved({ data: breakpoint.id });
+        this._breakpointAdded({ data: breakpoint });
+    },
+
+    _parsedScriptSource: function(event)
+    {
+        var url = event.data.sourceURL;
+        var breakpoints = WebInspector.debuggerModel.breakpoints;
+        for (var id in breakpoints) {
+            if (!(id in this._items))
+                this._breakpointAdded({ data: breakpoints[id] });
+        }
+    },
+
+    _breakpointEnableChanged: function(enabled, event)
+    {
+        var breakpointId = event.data;
+        var breakpointItem = this._items[breakpointId];
+        if (breakpointItem)
+            breakpointItem.checkbox.checked = enabled;
+    },
+
+    _breakpointItemCheckboxClicked: function(breakpointId, event)
+    {
+        var breakpoint = WebInspector.debuggerModel.breakpointForId(breakpointId);
+        WebInspector.debuggerModel.updateBreakpoint(breakpointId, breakpoint.condition, event.target.checked);
+
+        // Breakpoint element may have it's own click handler.
+        event.stopPropagation();
+    },
+
+    _contextMenuEventFired: function(breakpointId, event)
+    {
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), this._removeBreakpoint.bind(this, breakpointId));
+        contextMenu.show(event);
+    },
+
+    _debuggerPaused: function(event)
+    {
+        var breakpoint = event.data.breakpoint;
+        if (!breakpoint)
+            return;
+        var breakpointItem = this._items[breakpoint.id];
+        if (!breakpointItem)
+            return;
+        breakpointItem.element.addStyleClass("breakpoint-hit");
+        this._lastHitBreakpointItem = breakpointItem;
+    },
+
+    _debuggerResumed: function()
+    {
+        if (this._lastHitBreakpointItem) {
+            this._lastHitBreakpointItem.element.removeStyleClass("breakpoint-hit");
+            delete this._lastHitBreakpointItem;
+        }
+    },
+
+    _addListElement: function(element, beforeElement)
+    {
+        if (beforeElement)
+            this.listElement.insertBefore(element, beforeElement);
+        else {
+            if (!this.listElement.firstChild) {
+                this.bodyElement.removeChild(this.emptyElement);
+                this.bodyElement.appendChild(this.listElement);
+            }
+            this.listElement.appendChild(element);
+        }
+    },
+
+    _removeListElement: function(element)
+    {
+        this.listElement.removeChild(element);
+        if (!this.listElement.firstChild) {
+            this.bodyElement.removeChild(this.listElement);
+            this.bodyElement.appendChild(this.emptyElement);
+        }
+    },
+
+    _projectChanged: function()
+    {
+        this.listElement.removeChildren();
+        if (this.listElement.parentElement) {
+            this.bodyElement.removeChild(this.listElement);
+            this.bodyElement.appendChild(this.emptyElement);
+        }
+        this._items = {};
+    },
+
+    _compare: function(x, y)
+    {
+        if (x !== y)
+            return x < y ? -1 : 1;
+        return 0;
+    },
+
+    _compareBreakpoints: function(b1, b2)
+    {
+        return this._compare(b1.url, b2.url) || this._compare(b1.lineNumber, b2.lineNumber);
+    },
+
+    _setupBreakpointElement: function(data, element)
+    {
+        var sourceID;
+        var lineNumber = data.lineNumber;
+        if (data.locations.length) {
+            sourceID = data.locations[0].sourceID;
+            lineNumber = data.locations[0].lineNumber;
+        }
+
+        var displayName = data.url ? WebInspector.displayNameForURL(data.url) : WebInspector.UIString("(program)");
+        var labelElement = document.createTextNode(displayName + ":" + (lineNumber + 1));
+        element.appendChild(labelElement);
+
+        var sourceTextElement = document.createElement("div");
+        sourceTextElement.className = "source-text monospace";
+        element.appendChild(sourceTextElement);
+
+        if (sourceID) {
+            function didGetSourceLine(text)
+            {
+                sourceTextElement.textContent = text;
+            }
+            var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
+            script.sourceLine(lineNumber, didGetSourceLine.bind(this));
+        }
+
+        element.addStyleClass("cursor-pointer");
+        var clickHandler = WebInspector.panels.scripts.showSourceLine.bind(WebInspector.panels.scripts, data.url, lineNumber + 1);
+        element.addEventListener("click", clickHandler, false);
+    },
+
+    _removeBreakpoint: function(breakpointId)
+    {
+        WebInspector.debuggerModel.removeBreakpoint(breakpointId);
+    }
+}
+
+WebInspector.JavaScriptBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.NativeBreakpointsSidebarPane = function(title)
+{
+    WebInspector.SidebarPane.call(this, title);
+
+    this.listElement = document.createElement("ol");
+    this.listElement.className = "breakpoint-list";
+
+    this.emptyElement = document.createElement("div");
+    this.emptyElement.className = "info";
+    this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
+
+    this.bodyElement.appendChild(this.emptyElement);
+
+    WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
+}
+
+WebInspector.NativeBreakpointsSidebarPane.prototype = {
+    addBreakpointItem: function(breakpointItem)
+    {
+        var element = breakpointItem.element;
+        element._breakpointItem = breakpointItem;
+
+        breakpointItem.addEventListener("breakpoint-hit", this.expand, this);
+        breakpointItem.addEventListener("removed", this._removeListElement.bind(this, element), this);
+
+        var currentElement = this.listElement.firstChild;
+        while (currentElement) {
+            if (currentElement._breakpointItem && currentElement._breakpointItem.compareTo(element._breakpointItem) > 0)
+                break;
+            currentElement = currentElement.nextSibling;
+        }
+        this._addListElement(element, currentElement);
+
+        if (breakpointItem.click) {
+            element.addStyleClass("cursor-pointer");
+            element.addEventListener("click", breakpointItem.click.bind(breakpointItem), false);
+        }
+        element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this, breakpointItem), true);
+    },
+
+    _contextMenuEventFired: function(breakpointItem, event)
+    {
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), breakpointItem.remove.bind(breakpointItem));
+        contextMenu.show(event);
+    },
+
+    _addListElement: function(element, beforeElement)
+    {
+        if (beforeElement)
+            this.listElement.insertBefore(element, beforeElement);
+        else {
+            if (!this.listElement.firstChild) {
+                this.bodyElement.removeChild(this.emptyElement);
+                this.bodyElement.appendChild(this.listElement);
+            }
+            this.listElement.appendChild(element);
+        }
+    },
+
+    _removeListElement: function(element)
+    {
+        this.listElement.removeChild(element);
+        if (!this.listElement.firstChild) {
+            this.bodyElement.removeChild(this.listElement);
+            this.bodyElement.appendChild(this.emptyElement);
+        }
+    },
+
+    _projectChanged: function()
+    {
+        this.listElement.removeChildren();
+        if (this.listElement.parentElement) {
+            this.bodyElement.removeChild(this.listElement);
+            this.bodyElement.appendChild(this.emptyElement);
+        }
+    }
+}
+
+WebInspector.NativeBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.XHRBreakpointsSidebarPane = function()
+{
+    WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));
+
+    function addButtonClicked(event)
+    {
+        event.stopPropagation();
+        this._startEditingBreakpoint(null);
+    }
+
+    var addButton = document.createElement("button");
+    addButton.className = "add";
+    addButton.addEventListener("click", addButtonClicked.bind(this), false);
+    this.titleElement.appendChild(addButton);
+}
+
+WebInspector.XHRBreakpointsSidebarPane.prototype = {
+    addBreakpointItem: function(breakpointItem)
+    {
+        WebInspector.NativeBreakpointsSidebarPane.prototype.addBreakpointItem.call(this, breakpointItem);
+        breakpointItem._labelElement.addEventListener("dblclick", this._startEditingBreakpoint.bind(this, breakpointItem), false);
+    },
+
+    _startEditingBreakpoint: function(breakpointItem)
+    {
+        if (this._editingBreakpoint)
+            return;
+        this._editingBreakpoint = true;
+
+        if (!this.expanded)
+            this.expanded = true;
+
+        var inputElement = document.createElement("span");
+        inputElement.className = "breakpoint-condition editing";
+        if (breakpointItem) {
+            breakpointItem.populateEditElement(inputElement);
+            this.listElement.insertBefore(inputElement, breakpointItem.element);
+            breakpointItem.element.addStyleClass("hidden");
+        } else
+            this._addListElement(inputElement, this.listElement.firstChild);
+
+        var commitHandler = this._hideEditBreakpointDialog.bind(this, inputElement, true, breakpointItem);
+        var cancelHandler = this._hideEditBreakpointDialog.bind(this, inputElement, false, breakpointItem);
+        WebInspector.startEditing(inputElement, {
+            commitHandler: commitHandler,
+            cancelHandler: cancelHandler
+        });
+    },
+
+    _hideEditBreakpointDialog: function(inputElement, accept, breakpointItem)
+    {
+        this._removeListElement(inputElement);
+        this._editingBreakpoint = false;
+        if (accept) {
+            if (breakpointItem)
+                breakpointItem.remove();
+            WebInspector.breakpointManager.createXHRBreakpoint(inputElement.textContent.toLowerCase());
+        } else if (breakpointItem)
+            breakpointItem.element.removeStyleClass("hidden");
+    }
+}
+
+WebInspector.XHRBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype;
+
+WebInspector.BreakpointItem = function(breakpoint)
+{
+    this._breakpoint = breakpoint;
+
+    this._element = document.createElement("li");
+
+    var checkboxElement = document.createElement("input");
+    checkboxElement.className = "checkbox-elem";
+    checkboxElement.type = "checkbox";
+    checkboxElement.checked = this._breakpoint.enabled;
+    checkboxElement.addEventListener("click", this._checkboxClicked.bind(this), false);
+    this._element.appendChild(checkboxElement);
+
+    this._createLabelElement();
+
+    this._breakpoint.addEventListener("enable-changed", this._enableChanged, this);
+    this._breakpoint.addEventListener("hit-state-changed", this._hitStateChanged, this);
+    this._breakpoint.addEventListener("label-changed", this._labelChanged, this);
+    this._breakpoint.addEventListener("removed", this.dispatchEventToListeners.bind(this, "removed"));
+    if (breakpoint.click)
+        this.click = breakpoint.click.bind(breakpoint);
+}
+
+WebInspector.BreakpointItem.prototype = {
+    get element()
+    {
+        return this._element;
+    },
+
+    compareTo: function(other)
+    {
+        return this._breakpoint.compareTo(other._breakpoint);
+    },
+
+    populateEditElement: function(element)
+    {
+        this._breakpoint.populateEditElement(element);
+    },
+
+    remove: function()
+    {
+        this._breakpoint.remove();
+    },
+
+    _checkboxClicked: function(event)
+    {
+        this._breakpoint.enabled = !this._breakpoint.enabled;
+
+        // Breakpoint element may have it's own click handler.
+        event.stopPropagation();
+    },
+
+    _enableChanged: function(event)
+    {
+        var checkbox = this._element.firstChild;
+        checkbox.checked = this._breakpoint.enabled;
+    },
+
+    _hitStateChanged: function(event)
+    {
+        if (event.target.hit) {
+            this._element.addStyleClass("breakpoint-hit");
+            this.dispatchEventToListeners("breakpoint-hit");
+        } else
+            this._element.removeStyleClass("breakpoint-hit");
+    },
+
+    _labelChanged: function(event)
+    {
+        this._element.removeChild(this._labelElement);
+        this._createLabelElement();
+    },
+
+    _createLabelElement: function()
+    {
+        this._labelElement = document.createElement("span");
+        this._breakpoint.populateLabelElement(this._labelElement);
+        this._element.appendChild(this._labelElement);
+    }
+}
+
+WebInspector.BreakpointItem.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.EventListenerBreakpointsSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
+
+    this.categoriesElement = document.createElement("ol");
+    this.categoriesElement.tabIndex = 0;
+    this.categoriesElement.addStyleClass("properties-tree event-listener-breakpoints");
+    this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
+    this.bodyElement.appendChild(this.categoriesElement);
+
+    WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
+    WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.EventListenerBreakpointAdded, this._breakpointAdded, this);
+
+    this._breakpointItems = {};
+    this._createCategory(WebInspector.UIString("Keyboard"), "listener", ["keydown", "keyup", "keypress", "textInput"]);
+    this._createCategory(WebInspector.UIString("Mouse"), "listener", ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]);
+    // FIXME: uncomment following once inspector stops being drop targer in major ports.
+    // Otherwise, inspector page reacts on drop event and tries to load the event data.
+    // this._createCategory(WebInspector.UIString("Drag"), "listener", ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]);
+    this._createCategory(WebInspector.UIString("Control"), "listener", ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
+    this._createCategory(WebInspector.UIString("Clipboard"), "listener", ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
+    this._createCategory(WebInspector.UIString("Load"), "listener", ["load", "unload", "abort", "error"]);
+    this._createCategory(WebInspector.UIString("DOM Mutation"), "listener", ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
+    this._createCategory(WebInspector.UIString("Device"), "listener", ["deviceorientation", "devicemotion"]);
+    this._createCategory(WebInspector.UIString("Timer"), "instrumentation", ["setTimer", "clearTimer", "timerFired"]);
+}
+
+WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
+    _createCategory: function(name, type, eventNames)
+    {
+        var categoryItem = {};
+        categoryItem.element = new TreeElement(name);
+        this.categoriesTreeOutline.appendChild(categoryItem.element);
+        categoryItem.element.listItemElement.addStyleClass("event-category");
+        categoryItem.element.selectable = true;
+
+        categoryItem.checkbox = this._createCheckbox(categoryItem.element);
+        categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);
+
+        categoryItem.children = {};
+        for (var i = 0; i < eventNames.length; ++i) {
+            var eventName = type + ":" + eventNames[i];
+
+            var breakpointItem = {};
+            var title = WebInspector.EventListenerBreakpointView.eventNameForUI(eventName);
+            breakpointItem.element = new TreeElement(title);
+            categoryItem.element.appendChild(breakpointItem.element);
+            var hitMarker = document.createElement("div");
+            hitMarker.className = "breakpoint-hit-marker";
+            breakpointItem.element.listItemElement.appendChild(hitMarker);
+            breakpointItem.element.listItemElement.addStyleClass("source-code");
+            breakpointItem.element.selectable = true;
+
+            breakpointItem.checkbox = this._createCheckbox(breakpointItem.element);
+            breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpointItem), true);
+            breakpointItem.parent = categoryItem;
+            breakpointItem.eventName = eventName;
+
+            this._breakpointItems[eventName] = breakpointItem;
+            categoryItem.children[eventName] = breakpointItem;
+        }
+    },
+
+    _createCheckbox: function(treeElement)
+    {
+        var checkbox = document.createElement("input");
+        checkbox.className = "checkbox-elem";
+        checkbox.type = "checkbox";
+        treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild);
+        return checkbox;
+    },
+
+    _categoryCheckboxClicked: function(categoryItem)
+    {
+        var checked = categoryItem.checkbox.checked;
+        for (var eventName in categoryItem.children) {
+            var breakpointItem = categoryItem.children[eventName];
+            if (breakpointItem.checkbox.checked !== checked) {
+                breakpointItem.checkbox.checked = checked;
+                this._breakpointCheckboxClicked(breakpointItem);
+            }
+        }
+    },
+
+    _breakpointCheckboxClicked: function(breakpointItem)
+    {
+        if (breakpointItem.checkbox.checked)
+            WebInspector.breakpointManager.createEventListenerBreakpoint(breakpointItem.eventName);
+        else
+            breakpointItem.breakpoint.remove();
+    },
+
+    _breakpointAdded: function(event)
+    {
+        var breakpoint = event.data;
+
+        var breakpointItem = this._breakpointItems[breakpoint.eventName];
+        breakpointItem.breakpoint = breakpoint;
+        breakpoint.addEventListener("hit-state-changed", this._breakpointHitStateChanged.bind(this, breakpointItem));
+        breakpoint.addEventListener("removed", this._breakpointRemoved.bind(this, breakpointItem));
+        breakpointItem.checkbox.checked = true;
+        this._updateCategoryCheckbox(breakpointItem);
+    },
+
+    _breakpointHitStateChanged: function(breakpointItem, event)
+    {
+        if (event.target.hit) {
+            this.expanded = true;
+            var categoryItem = breakpointItem.parent;
+            categoryItem.element.expand();
+            breakpointItem.element.listItemElement.addStyleClass("breakpoint-hit");
+        } else
+            breakpointItem.element.listItemElement.removeStyleClass("breakpoint-hit");
+    },
+
+    _breakpointRemoved: function(breakpointItem)
+    {
+        breakpointItem.breakpoint = null;
+        breakpointItem.checkbox.checked = false;
+        this._updateCategoryCheckbox(breakpointItem);
+    },
+
+    _updateCategoryCheckbox: function(breakpointItem)
+    {
+        var categoryItem = breakpointItem.parent;
+        var hasEnabled = false, hasDisabled = false;
+        for (var eventName in categoryItem.children) {
+            var breakpointItem = categoryItem.children[eventName];
+            if (breakpointItem.checkbox.checked)
+                hasEnabled = true;
+            else
+                hasDisabled = true;
+        }
+        categoryItem.checkbox.checked = hasEnabled;
+        categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
+    },
+
+    _projectChanged: function()
+    {
+        for (var eventName in this._breakpointItems) {
+            var breakpointItem = this._breakpointItems[eventName];
+            breakpointItem.breakpoint = null;
+            breakpointItem.checkbox.checked = false;
+            this._updateCategoryCheckbox(breakpointItem);
+        }
+    }
+}
+
+WebInspector.EventListenerBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSCompletions.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSCompletions.js
new file mode 100644
index 0000000..ba3aca2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSCompletions.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 Nikita Vasilyev. All rights reserved.
+ * Copyright (C) 2010 Joseph Pecoraro. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CSSCompletions = function(values, acceptEmptyPrefix)
+{
+    this._values = values.slice();
+    this._values.sort();
+    this._acceptEmptyPrefix = acceptEmptyPrefix;
+}
+
+WebInspector.CSSCompletions.prototype = {
+    startsWith: function(prefix)
+    {
+        var firstIndex = this._firstIndexOfPrefix(prefix);
+        if (firstIndex === -1)
+            return [];
+
+        var results = [];
+        while (firstIndex < this._values.length && this._values[firstIndex].indexOf(prefix) === 0)
+            results.push(this._values[firstIndex++]);
+        return results;
+    },
+
+    firstStartsWith: function(prefix)
+    {
+        var foundIndex = this._firstIndexOfPrefix(prefix);
+        return (foundIndex === -1 ? "" : this._values[foundIndex]);
+    },
+
+    _firstIndexOfPrefix: function(prefix)
+    {
+        if (!this._values.length)
+            return -1;
+        if (!prefix)
+            return this._acceptEmptyPrefix ? 0 : -1;
+
+        var maxIndex = this._values.length - 1;
+        var minIndex = 0;
+        var foundIndex;
+
+        do {
+            var middleIndex = (maxIndex + minIndex) >> 1;
+            if (this._values[middleIndex].indexOf(prefix) === 0) {
+                foundIndex = middleIndex;
+                break;
+            }
+            if (this._values[middleIndex] < prefix)
+                minIndex = middleIndex + 1;
+            else
+                maxIndex = middleIndex - 1;
+        } while (minIndex <= maxIndex);
+
+        if (foundIndex === undefined)
+            return -1;
+
+        while (foundIndex && this._values[foundIndex - 1].indexOf(prefix) === 0)
+            foundIndex--;
+
+        return foundIndex;
+    },
+
+    keySet: function()
+    {
+        return this._values.keySet();
+    },
+
+    next: function(str, prefix)
+    {
+        return this._closest(str, prefix, 1);
+    },
+
+    previous: function(str, prefix)
+    {
+        return this._closest(str, prefix, -1);
+    },
+
+    _closest: function(str, prefix, shift)
+    {
+        if (!str)
+            return "";
+
+        var index = this._values.indexOf(str);
+        if (index === -1)
+            return "";
+
+        if (!prefix) {
+            index = (index + this._values.length + shift) % this._values.length;
+            return this._values[index];
+        }
+
+        var propertiesWithPrefix = this.startsWith(prefix);
+        var j = propertiesWithPrefix.indexOf(str);
+        j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;
+        return propertiesWithPrefix[j];
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSKeywordCompletions.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSKeywordCompletions.js
new file mode 100755
index 0000000..de2072a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSKeywordCompletions.js
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CSSKeywordCompletions = {
+    forProperty: function(propertyName)
+    {
+        var acceptedKeywords = ["initial"];
+        if (propertyName in this._propertyKeywordMap)
+            acceptedKeywords = acceptedKeywords.concat(this._propertyKeywordMap[propertyName]);
+        if (propertyName in this._colorAwareProperties)
+            acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._colors);
+        if (propertyName in WebInspector.StylesSidebarPane.InheritedProperties)
+            acceptedKeywords.push("inherit");
+        return new WebInspector.CSSCompletions(acceptedKeywords, true);
+    }
+};
+
+WebInspector.CSSKeywordCompletions._colors = [
+    "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red",
+    "silver", "teal", "white", "yellow", "transparent", "currentcolor", "grey", "aliceblue", "antiquewhite",
+    "aquamarine", "azure", "beige", "bisque", "blanchedalmond", "blueviolet", "brown", "burlywood", "cadetblue",
+    "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
+    "darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange",
+    "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey",
+    "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
+    "floralwhite", "forestgreen", "gainsboro", "ghostwhite", "gold", "goldenrod", "greenyellow", "honeydew", "hotpink",
+    "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue",
+    "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
+    "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow",
+    "limegreen", "linen", "magenta", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
+    "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream",
+    "mistyrose", "moccasin", "navajowhite", "oldlace", "olivedrab", "orangered", "orchid", "palegoldenrod", "palegreen",
+    "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "rosybrown",
+    "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "skyblue", "slateblue",
+    "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "thistle", "tomato", "turquoise", "violet",
+    "wheat", "whitesmoke", "yellowgreen"
+],
+
+WebInspector.CSSKeywordCompletions._colorAwareProperties = [
+    "background", "background-color", "border", "border-color", "border-top", "border-right", "border-bottom",
+    "border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "color",
+    "outline", "outline-color", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color",
+    "text-shadow", "text-underline", "text-underline-color", "-webkit-text-emphasis", "-webkit-text-emphasis-color"
+].keySet();
+
+WebInspector.CSSKeywordCompletions._propertyKeywordMap = {
+    "table-layout": [
+        "auto", "fixed"
+    ],
+    "visibility": [
+        "hidden", "visible", "collapse"
+    ],
+    "background-repeat": [
+        "repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round"
+    ],
+    "text-underline": [
+        "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
+    ],
+    "content": [
+        "list-item", "close-quote", "no-close-quote", "no-open-quote", "open-quote"
+    ],
+    "list-style-image": [
+        "none"
+    ],
+    "clear": [
+        "none", "left", "right", "both"
+    ],
+    "text-underline-mode": [
+        "continuous", "skip-white-space"
+    ],
+    "overflow-x": [
+        "hidden", "auto", "visible", "overlay", "scroll"
+    ],
+    "stroke-linejoin": [
+        "round", "miter", "bevel"
+    ],
+    "baseline-shift": [
+        "baseline", "sub", "super"
+    ],
+    "border-bottom-width": [
+        "medium", "thick", "thin"
+    ],
+    "marquee-speed": [
+        "normal", "slow", "fast"
+    ],
+    "margin-top-collapse": [
+        "collapse", "separate", "discard"
+    ],
+    "max-height": [
+        "none"
+    ],
+    "box-orient": [
+        "horizontal", "vertical", "inline-axis", "block-axis"
+    ],
+    "font-stretch": [
+        "normal", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
+        "semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
+    ],
+    "-webkit-color-correction": [
+        "default", "srgb"
+    ],
+    "text-underline-style": [
+        "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
+    ],
+    "text-overline-mode": [
+        "continuous", "skip-white-space"
+    ],
+    "-webkit-background-composite": [
+        "highlight", "clear", "copy", "source-over", "source-in", "source-out", "source-atop", "destination-over",
+        "destination-in", "destination-out", "destination-atop", "xor", "plus-darker", "plus-lighter"
+    ],
+    "border-left-width": [
+        "medium", "thick", "thin"
+    ],
+    "-webkit-writing-mode": [
+        "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt"
+    ],
+    "text-line-through-mode": [
+        "continuous", "skip-white-space"
+    ],
+    "border-collapse": [
+        "collapse", "separate"
+    ],
+    "page-break-inside": [
+        "auto", "avoid"
+    ],
+    "border-top-width": [
+        "medium", "thick", "thin"
+    ],
+    "outline-color": [
+        "invert"
+    ],
+    "text-line-through-style": [
+        "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
+    ],
+    "outline-style": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "cursor": [
+        "none", "copy", "auto", "crosshair", "default", "pointer", "move", "vertical-text", "cell", "context-menu",
+        "alias", "progress", "no-drop", "not-allowed", "-webkit-zoom-in", "-webkit-zoom-out", "e-resize", "ne-resize",
+        "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "ew-resize", "ns-resize",
+        "nesw-resize", "nwse-resize", "col-resize", "row-resize", "text", "wait", "help", "all-scroll", "-webkit-grab",
+        "-webkit-grabbing"
+    ],
+    "border-width": [
+        "medium", "thick", "thin"
+    ],
+    "size": [
+        "a3", "a4", "a5", "b4", "b5", "landscape", "ledger", "legal", "letter", "portrait"
+    ],
+    "background-size": [
+        "contain", "cover"
+    ],
+    "direction": [
+        "ltr", "rtl"
+    ],
+    "marquee-direction": [
+        "left", "right", "auto", "reverse", "forwards", "backwards", "ahead", "up", "down"
+    ],
+    "enable-background": [
+        "accumulate", "new"
+    ],
+    "float": [
+        "none", "left", "right"
+    ],
+    "overflow-y": [
+        "hidden", "auto", "visible", "overlay", "scroll"
+    ],
+    "margin-bottom-collapse": [
+        "collapse",  "separate", "discard"
+    ],
+    "box-reflect": [
+        "left", "right", "above", "below"
+    ],
+    "overflow": [
+        "hidden", "auto", "visible", "overlay", "scroll"
+    ],
+    "text-rendering": [
+        "auto", "optimizespeed", "optimizelegibility", "geometricprecision"
+    ],
+    "text-align": [
+        "-webkit-auto", "left", "right", "center", "justify", "-webkit-left", "-webkit-right", "-webkit-center"
+    ],
+    "list-style-position": [
+        "outside", "inside"
+    ],
+    "margin-bottom": [
+        "auto"
+    ],
+    "color-interpolation": [
+        "linearrgb"
+    ],
+    "background-origin": [
+        "border-box", "content-box", "padding-box"
+    ],
+    "word-wrap": [
+        "normal", "break-word"
+    ],
+    "font-weight": [
+        "normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"
+    ],
+    "margin-before-collapse": [
+        "collapse", "separate", "discard"
+    ],
+    "text-overline-width": [
+        "normal", "medium", "auto", "thick", "thin"
+    ],
+    "text-transform": [
+        "none", "capitalize", "uppercase", "lowercase"
+    ],
+    "border-right-style": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "border-left-style": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "-webkit-text-emphasis": [
+        "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
+    ],
+    "font-style": [
+        "italic", "oblique", "normal"
+    ],
+    "speak": [
+        "none", "normal", "spell-out", "digits", "literal-punctuation", "no-punctuation"
+    ],
+    "text-line-through": [
+        "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave", "continuous",
+        "skip-white-space"
+    ],
+    "color-rendering": [
+        "auto", "optimizespeed", "optimizequality"
+    ],
+    "list-style-type": [
+        "none", "disc", "circle", "square", "decimal", "decimal-leading-zero", "arabic-indic", "binary", "bengali",
+        "cambodian", "khmer", "devanagari", "gujarati", "gurmukhi", "kannada", "lower-hexadecimal", "lao", "malayalam",
+        "mongolian", "myanmar", "octal", "oriya", "persian", "urdu", "telugu", "tibetan", "thai", "upper-hexadecimal",
+        "lower-roman", "upper-roman", "lower-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "afar",
+        "ethiopic-halehame-aa-et", "ethiopic-halehame-aa-er", "amharic", "ethiopic-halehame-am-et", "amharic-abegede",
+        "ethiopic-abegede-am-et", "cjk-earthly-branch", "cjk-heavenly-stem", "ethiopic", "ethiopic-halehame-gez",
+        "ethiopic-abegede", "ethiopic-abegede-gez", "hangul-consonant", "hangul", "lower-norwegian", "oromo",
+        "ethiopic-halehame-om-et", "sidama", "ethiopic-halehame-sid-et", "somali", "ethiopic-halehame-so-et", "tigre",
+        "ethiopic-halehame-tig", "tigrinya-er", "ethiopic-halehame-ti-er", "tigrinya-er-abegede",
+        "ethiopic-abegede-ti-er", "tigrinya-et", "ethiopic-halehame-ti-et", "tigrinya-et-abegede",
+        "ethiopic-abegede-ti-et", "upper-greek", "upper-norwegian", "asterisks", "footnotes", "hebrew", "armenian",
+        "lower-armenian", "upper-armenian", "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
+        "katakana-iroha"
+    ],
+    "-webkit-text-combine": [
+        "none", "horizontal"
+    ],
+    "outline": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "font": [
+        "caption", "icon", "menu", "message-box", "small-caption", "-webkit-mini-control", "-webkit-small-control",
+        "-webkit-control", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter",
+        "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium",
+        "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", "larger", "serif", "sans-serif", "cursive",
+        "fantasy", "monospace", "-webkit-body"
+    ],
+    "dominant-baseline": [
+        "middle", "auto", "central", "text-before-edge", "text-after-edge", "ideographic", "alphabetic", "hanging",
+        "mathematical", "use-script", "no-change", "reset-size"
+    ],
+    "display": [
+        "none", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table",
+        "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group",
+        "table-column", "table-cell", "table-caption", "-webkit-box", "-webkit-inline-box", "-wap-marquee"
+    ],
+    "-webkit-text-emphasis-position": [
+        "over", "under"
+    ],
+    "image-rendering": [
+        "auto", "optimizespeed", "optimizequality"
+    ],
+    "alignment-baseline": [
+        "baseline", "middle", "auto", "before-edge", "after-edge", "central", "text-before-edge", "text-after-edge",
+        "ideographic", "alphabetic", "hanging", "mathematical"
+    ],
+    "outline-width": [
+        "medium", "thick", "thin"
+    ],
+    "text-line-through-width": [
+        "normal", "medium", "auto", "thick", "thin"
+    ],
+    "box-align": [
+        "baseline", "center", "stretch", "start", "end"
+    ],
+    "border-right-width": [
+        "medium", "thick", "thin"
+    ],
+    "border-top-style": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "line-height": [
+        "normal"
+    ],
+    "text-overflow": [
+        "clip", "ellipsis"
+    ],
+    "box-direction": [
+        "normal", "reverse"
+    ],
+    "margin-after-collapse": [
+        "collapse", "separate", "discard"
+    ],
+    "page-break-before": [
+        "left", "right", "auto", "always", "avoid"
+    ],
+    "-webkit-hyphens": [
+        "none", "auto", "manual"
+    ],
+    "border-image": [
+        "repeat", "stretch"
+    ],
+    "text-decoration": [
+        "blink", "line-through", "overline", "underline"
+    ],
+    "position": [
+        "absolute", "fixed", "relative", "static"
+    ],
+    "font-family": [
+        "serif", "sans-serif", "cursive", "fantasy", "monospace", "-webkit-body"
+    ],
+    "text-overflow-mode": [
+        "clip", "ellipsis"
+    ],
+    "border-bottom-style": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "unicode-bidi": [
+        "normal", "bidi-override", "embed"
+    ],
+    "clip-rule": [
+        "nonzero", "evenodd"
+    ],
+    "margin-left": [
+        "auto"
+    ],
+    "margin-top": [
+        "auto"
+    ],
+    "zoom": [
+        "document", "reset"
+    ],
+    "text-overline-style": [
+        "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
+    ],
+    "max-width": [
+        "none"
+    ],
+    "empty-cells": [
+        "hide", "show"
+    ],
+    "pointer-events": [
+        "none", "all", "auto", "visible", "visiblepainted", "visiblefill", "visiblestroke", "painted", "fill", "stroke"
+    ],
+    "letter-spacing": [
+        "normal"
+    ],
+    "background-clip": [
+        "border-box", "content-box", "padding-box"
+    ],
+    "-webkit-font-smoothing": [
+        "none", "auto", "antialiased", "subpixel-antialiased"
+    ],
+    "border": [
+        "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
+    ],
+    "font-size": [
+        "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller",
+        "larger"
+    ],
+    "font-variant": [
+        "small-caps", "normal"
+    ],
+    "vertical-align": [
+        "baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-webkit-baseline-middle"
+    ],
+    "marquee-style": [
+        "none", "scroll", "slide", "alternate"
+    ],
+    "white-space": [
+        "normal", "nowrap", "pre", "pre-line", "pre-wrap"
+    ],
+    "text-underline-width": [
+        "normal", "medium", "auto", "thick", "thin"
+    ],
+    "box-lines": [
+        "single", "multiple"
+    ],
+    "page-break-after": [
+        "left", "right", "auto", "always", "avoid"
+    ],
+    "clip-path": [
+        "none"
+    ],
+    "margin": [
+        "auto"
+    ],
+    "marquee-repetition": [
+        "infinite"
+    ],
+    "margin-right": [
+        "auto"
+    ],
+    "-webkit-text-emphasis-style": [
+        "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
+    ]
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSStyleModel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSStyleModel.js
new file mode 100644
index 0000000..69bd7a9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CSSStyleModel.js
@@ -0,0 +1,574 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CSSStyleModel = function()
+{
+}
+
+WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray)
+{
+    var result = [];
+    for (var i = 0; i < ruleArray.length; ++i)
+        result.push(WebInspector.CSSRule.parsePayload(ruleArray[i]));
+    return result;
+}
+
+WebInspector.CSSStyleModel.prototype = {
+    getStylesAsync: function(nodeId, userCallback)
+    {
+        function callback(userCallback, payload)
+        {
+            if (!payload) {
+                if (userCallback)
+                    userCallback(null);
+                return;
+            }
+
+            var result = {};
+            if ("inlineStyle" in payload)
+                result.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.inlineStyle);
+
+            result.computedStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.computedStyle);
+            result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(payload.matchedCSSRules);
+
+            result.styleAttributes = {};
+            for (var name in payload.styleAttributes)
+                result.styleAttributes[name] = WebInspector.CSSStyleDeclaration.parsePayload(payload.styleAttributes[name]);
+
+            result.pseudoElements = [];
+            for (var i = 0; i < payload.pseudoElements.length; ++i) {
+                var entryPayload = payload.pseudoElements[i];
+                result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) });
+            }
+
+            result.inherited = [];
+            for (var i = 0; i < payload.inherited.length; ++i) {
+                var entryPayload = payload.inherited[i];
+                var entry = {};
+                if ("inlineStyle" in entryPayload)
+                    entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle);
+                if ("matchedCSSRules" in entryPayload)
+                    entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules);
+                result.inherited.push(entry);
+            }
+
+            if (userCallback)
+                userCallback(result);
+        }
+
+        InspectorBackend.getStylesForNode(nodeId, callback.bind(null, userCallback));
+    },
+
+    getComputedStyleAsync: function(nodeId, userCallback)
+    {
+        function callback(userCallback, stylePayload)
+        {
+            if (!stylePayload)
+                userCallback(null);
+            else
+                userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
+        }
+
+        InspectorBackend.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
+    },
+
+    getInlineStyleAsync: function(nodeId, userCallback)
+    {
+        function callback(userCallback, stylePayload)
+        {
+            if (!stylePayload)
+                userCallback(null);
+            else
+                userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
+        }
+
+        InspectorBackend.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
+    },
+
+    setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback)
+    {
+        function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
+        {
+            var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
+            var rule = WebInspector.CSSRule.parsePayload(rulePayload);
+            successCallback(rule, doesAffectSelectedNode);
+            this._styleSheetChanged(rule.id.styleSheetId, true);
+        }
+
+        function callback(nodeId, successCallback, failureCallback, newSelector, rulePayload)
+        {
+            if (!rulePayload)
+                failureCallback();
+            else
+                InspectorBackend.querySelectorAll(nodeId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+        }
+
+        InspectorBackend.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback));
+    },
+
+    addRule: function(nodeId, selector, successCallback, failureCallback)
+    {
+        function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
+        {
+            var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
+            var rule = WebInspector.CSSRule.parsePayload(rulePayload);
+            successCallback(rule, doesAffectSelectedNode);
+            this._styleSheetChanged(rule.id.styleSheetId, true);
+        }
+
+        function callback(successCallback, failureCallback, selector, rulePayload)
+        {
+            if (!rulePayload) {
+                // Invalid syntax for a selector
+                failureCallback();
+            } else
+                InspectorBackend.querySelectorAll(nodeId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+        }
+
+        InspectorBackend.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
+    },
+
+    _styleSheetChanged: function(styleSheetId, majorChange)
+    {
+        if (!majorChange || !styleSheetId)
+            return;
+
+        function callback(href, content)
+        {
+            var resource = WebInspector.resourceForURL(href);
+            if (resource && resource.type === WebInspector.Resource.Type.Stylesheet)
+                resource.setContent(content, this._onRevert.bind(this, styleSheetId));
+        }
+        InspectorBackend.getStyleSheetText(styleSheetId, callback.bind(this));
+    },
+
+    _onRevert: function(styleSheetId, contentToRevertTo)
+    {
+        function callback(success)
+        {
+            this._styleSheetChanged(styleSheetId, true);
+            this.dispatchEventToListeners("stylesheet changed");
+        }
+        InspectorBackend.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this));
+    }
+}
+
+WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.CSSStyleDeclaration = function(payload)
+{
+    this.id = payload.styleId;
+    this.properties = payload.properties;
+    this._shorthandValues = payload.shorthandValues;
+    this._livePropertyMap = {}; // LIVE properties (source-based or style-based) : { name -> CSSProperty }
+    this._allProperties = []; // ALL properties: [ CSSProperty ]
+    this._longhandProperties = {}; // shorthandName -> [ CSSProperty ]
+    this.__disabledProperties = {}; // DISABLED properties: { index -> CSSProperty }
+    var payloadPropertyCount = payload.cssProperties.length;
+
+    var propertyIndex = 0;
+    for (var i = 0; i < payloadPropertyCount; ++i) {
+        var property = new WebInspector.CSSProperty.parsePayload(this, i, payload.cssProperties[i]);
+        this._allProperties.push(property);
+        if (property.disabled)
+            this.__disabledProperties[i] = property;
+        if (!property.active && !property.styleBased)
+            continue;
+        var name = property.name;
+        this[propertyIndex] = name;
+        this._livePropertyMap[name] = property;
+
+        // Index longhand properties.
+        if (property.shorthand) { // only for parsed
+            var longhands = this._longhandProperties[property.shorthand];
+            if (!longhands) {
+                longhands = [];
+                this._longhandProperties[property.shorthand] = longhands;
+            }
+            longhands.push(property);
+        }
+        ++propertyIndex;
+    }
+    this.length = propertyIndex;
+    if ("cssText" in payload)
+        this.cssText = payload.cssText;
+}
+
+WebInspector.CSSStyleDeclaration.parsePayload = function(payload)
+{
+    return new WebInspector.CSSStyleDeclaration(payload);
+}
+
+WebInspector.CSSStyleDeclaration.prototype = {
+    get allProperties()
+    {
+        return this._allProperties;
+    },
+
+    getLiveProperty: function(name)
+    {
+        return this._livePropertyMap[name];
+    },
+
+    getPropertyValue: function(name)
+    {
+        var property = this._livePropertyMap[name];
+        return property ? property.value : "";
+    },
+
+    getPropertyPriority: function(name)
+    {
+        var property = this._livePropertyMap[name];
+        return property ? property.priority : "";
+    },
+
+    getPropertyShorthand: function(name)
+    {
+        var property = this._livePropertyMap[name];
+        return property ? property.shorthand : "";
+    },
+
+    isPropertyImplicit: function(name)
+    {
+        var property = this._livePropertyMap[name];
+        return property ? property.implicit : "";
+    },
+
+    styleTextWithShorthands: function()
+    {
+        var cssText = "";
+        var foundProperties = {};
+        for (var i = 0; i < this.length; ++i) {
+            var individualProperty = this[i];
+            var shorthandProperty = this.getPropertyShorthand(individualProperty);
+            var propertyName = (shorthandProperty || individualProperty);
+
+            if (propertyName in foundProperties)
+                continue;
+
+            if (shorthandProperty) {
+                var value = this.getShorthandValue(shorthandProperty);
+                var priority = this.getShorthandPriority(shorthandProperty);
+            } else {
+                var value = this.getPropertyValue(individualProperty);
+                var priority = this.getPropertyPriority(individualProperty);
+            }
+
+            foundProperties[propertyName] = true;
+
+            cssText += propertyName + ": " + value;
+            if (priority)
+                cssText += " !" + priority;
+            cssText += "; ";
+        }
+
+        return cssText;
+    },
+
+    getLonghandProperties: function(name)
+    {
+        return this._longhandProperties[name] || [];
+    },
+
+    getShorthandValue: function(shorthandProperty)
+    {
+        var property = this.getLiveProperty(shorthandProperty);
+        return property ? property.value : this._shorthandValues[shorthandProperty];
+    },
+
+    getShorthandPriority: function(shorthandProperty)
+    {
+        var priority = this.getPropertyPriority(shorthandProperty);
+        if (priority)
+            return priority;
+
+        var longhands = this._longhandProperties[shorthandProperty];
+        return longhands ? this.getPropertyPriority(longhands[0]) : null;
+    },
+
+    propertyAt: function(index)
+    {
+        return (index < this.allProperties.length) ? this.allProperties[index] : null;
+    },
+
+    pastLastSourcePropertyIndex: function()
+    {
+        for (var i = this.allProperties.length - 1; i >= 0; --i) {
+            var property = this.allProperties[i];
+            if (property.active || property.disabled)
+                return i + 1;
+        }
+        return 0;
+    },
+
+    newBlankProperty: function()
+    {
+        return new WebInspector.CSSProperty(this, this.pastLastSourcePropertyIndex(), "", "", "", "active", true, false, false, "");
+    },
+
+    insertPropertyAt: function(index, name, value, userCallback)
+    {
+        function callback(userCallback, payload)
+        {
+            if (!userCallback)
+                return;
+
+            if (!payload)
+                userCallback(null);
+            else {
+                userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload));
+                WebInspector.cssModel._styleSheetChanged(this.id.styleSheetId, true);
+            }
+        }
+
+        InspectorBackend.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
+    },
+
+    appendProperty: function(name, value, userCallback)
+    {
+        this.insertPropertyAt(this.allProperties.length, name, value, userCallback);
+    }
+}
+
+WebInspector.CSSRule = function(payload)
+{
+    this.id = payload.ruleId;
+    this.selectorText = payload.selectorText;
+    this.sourceLine = payload.sourceLine;
+    this.sourceURL = payload.sourceURL;
+    this.origin = payload.origin;
+    this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style);
+    this.style.parentRule = this;
+    this.selectorRange = payload.selectorRange;
+}
+
+WebInspector.CSSRule.parsePayload = function(payload)
+{
+    return new WebInspector.CSSRule(payload);
+}
+
+WebInspector.CSSRule.prototype = {
+    get isUserAgent()
+    {
+        return this.origin === "user-agent";
+    },
+
+    get isUser()
+    {
+        return this.origin === "user";
+    },
+
+    get isViaInspector()
+    {
+        return this.origin === "inspector";
+    },
+
+    get isRegular()
+    {
+        return this.origin === "";
+    }
+}
+
+WebInspector.CSSProperty = function(ownerStyle, index, name, value, priority, status, parsedOk, implicit, shorthand, text)
+{
+    this.ownerStyle = ownerStyle;
+    this.index = index;
+    this.name = name;
+    this.value = value;
+    this.priority = priority;
+    this.status = status;
+    this.parsedOk = parsedOk;
+    this.implicit = implicit;
+    this.shorthand = shorthand;
+    this.text = text;
+}
+
+WebInspector.CSSProperty.parsePayload = function(ownerStyle, index, payload)
+{
+    var result = new WebInspector.CSSProperty(
+        ownerStyle, index, payload.name, payload.value, payload.priority, payload.status, payload.parsedOk, payload.implicit, payload.shorthandName, payload.text);
+    return result;
+}
+
+WebInspector.CSSProperty.prototype = {
+    get propertyText()
+    {
+        if (this.text !== undefined)
+            return this.text;
+
+        if (this.name === "")
+            return "";
+        return this.name + ": " + this.value + (this.priority ? " !" + this.priority : "") + ";";
+    },
+
+    get isLive()
+    {
+        return this.active || this.styleBased;
+    },
+
+    get active()
+    {
+        return this.status === "active";
+    },
+
+    get styleBased()
+    {
+        return this.status === "style";
+    },
+
+    get inactive()
+    {
+        return this.status === "inactive";
+    },
+
+    get disabled()
+    {
+        return this.status === "disabled";
+    },
+
+    // Replaces "propertyName: propertyValue [!important];" in the stylesheet by an arbitrary propertyText.
+    setText: function(propertyText, majorChange, userCallback)
+    {
+        function enabledCallback(style)
+        {
+            if (style)
+                WebInspector.cssModel._styleSheetChanged(style.id.styleSheetId, majorChange);
+            if (userCallback)
+                userCallback(style);
+        }
+
+        function callback(stylePayload)
+        {
+            if (stylePayload) {
+                this.text = propertyText;
+                var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
+                var newProperty = style.allProperties[this.index];
+
+                if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) {
+                    newProperty.setDisabled(false, enabledCallback);
+                    return;
+                } else
+                    WebInspector.cssModel._styleSheetChanged(style.id.styleSheetId, majorChange);
+                if (userCallback)
+                    userCallback(style);
+            } else {
+                if (userCallback)
+                    userCallback(null);
+            }
+        }
+
+        if (!this.ownerStyle)
+            throw "No ownerStyle for property";
+
+        // An index past all the properties adds a new property to the style.
+        InspectorBackend.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
+    },
+
+    setValue: function(newValue, userCallback)
+    {
+        var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";"
+        this.setText(text, userCallback);
+    },
+
+    setDisabled: function(disabled, userCallback)
+    {
+        if (!this.ownerStyle && userCallback)
+            userCallback(null);
+        if (disabled === this.disabled && userCallback)
+            userCallback(this.ownerStyle);
+
+        function callback(stylePayload)
+        {
+            if (!userCallback)
+                return;
+            if (!stylePayload)
+                userCallback(null);
+            else {
+                var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
+                userCallback(style);
+                WebInspector.cssModel._styleSheetChanged(this.ownerStyle.id.styleSheetId, false);
+            }
+        }
+
+        InspectorBackend.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
+    }
+}
+
+WebInspector.CSSStyleSheet = function(payload)
+{
+    this.id = payload.styleSheetId;
+    this.sourceURL = payload.sourceURL;
+    this.title = payload.title;
+    this.disabled = payload.disabled;
+    this.rules = [];
+    this.styles = {};
+    for (var i = 0; i < payload.rules.length; ++i) {
+        var rule = WebInspector.CSSRule.parsePayload(payload.rules[i]);
+        this.rules.push(rule);
+        if (rule.style)
+            this.styles[rule.style.id] = rule.style;
+    }
+    if ("text" in payload)
+        this._text = payload.text;
+}
+
+WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback)
+{
+    function callback(styleSheetPayload)
+    {
+        if (!styleSheetPayload)
+            userCallback(null);
+        else
+            userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
+    }
+    InspectorBackend.getStyleSheet(styleSheetId, callback.bind(this));
+}
+
+WebInspector.CSSStyleSheet.prototype = {
+    getText: function()
+    {
+        return this._text;
+    },
+
+    setText: function(newText, userCallback)
+    {
+        function callback(styleSheetPayload)
+        {
+            if (!styleSheetPayload)
+                userCallback(null);
+            else {
+                userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
+                WebInspector.cssModel._styleSheetChanged(this.id, true);
+            }
+        }
+
+        InspectorBackend.setStyleSheetText(this.id, newText, callback.bind(this));
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CallStackSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CallStackSidebarPane.js
new file mode 100644
index 0000000..e9cfc64
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CallStackSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+}
+
+WebInspector.CallStackSidebarPane.prototype = {
+    update: function(details)
+    {
+        this.bodyElement.removeChildren();
+
+        this.placards = [];
+        delete this._selectedCallFrame;
+
+        if (!details) {
+            var infoElement = document.createElement("div");
+            infoElement.className = "info";
+            infoElement.textContent = WebInspector.UIString("Not Paused");
+            this.bodyElement.appendChild(infoElement);
+            return;
+        }
+
+        var callFrames = details.callFrames;
+        var title;
+        var subtitle;
+        var script;
+
+        for (var i = 0; i < callFrames.length; ++i) {
+            var callFrame = callFrames[i];
+            switch (callFrame.type) {
+            case "function":
+                title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
+                break;
+            case "program":
+                title = WebInspector.UIString("(program)");
+                break;
+            }
+
+            script = WebInspector.debuggerModel.scriptForSourceID(callFrame.sourceID);
+            if (script)
+                subtitle = WebInspector.displayNameForURL(script.sourceURL);
+            else
+                subtitle = WebInspector.UIString("(internal script)");
+
+            if (callFrame.line > 0) {
+                if (subtitle)
+                    subtitle += ":" + callFrame.line;
+                else
+                    subtitle = WebInspector.UIString("line %d", callFrame.line);
+            }
+
+            var placard = new WebInspector.Placard(title, subtitle);
+            placard.callFrame = callFrame;
+
+            placard.element.addEventListener("click", this._placardSelected.bind(this), false);
+
+            this.placards.push(placard);
+            this.bodyElement.appendChild(placard.element);
+        }
+
+        if (details.breakpoint)
+            this._scriptBreakpointHit();
+        else if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
+            this._nativeBreakpointHit(details.eventData);
+    },
+
+    get selectedCallFrame()
+    {
+        return this._selectedCallFrame;
+    },
+
+    set selectedCallFrame(x)
+    {
+        this._selectedCallFrame = x;
+
+        for (var i = 0; i < this.placards.length; ++i) {
+            var placard = this.placards[i];
+            placard.selected = (placard.callFrame === this._selectedCallFrame);
+        }
+
+        this.dispatchEventToListeners("call frame selected");
+    },
+
+    handleShortcut: function(event)
+    {
+        var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+        var handler = this._shortcuts[shortcut];
+        if (handler) {
+            handler(event);
+            event.handled = true;
+        }
+    },
+
+    _selectNextCallFrameOnStack: function()
+    {
+        var index = this._selectedCallFrameIndex();
+        if (index == -1)
+            return;
+        this._selectedPlacardByIndex(index + 1);
+    },
+
+    _selectPreviousCallFrameOnStack: function()
+    {
+        var index = this._selectedCallFrameIndex();
+        if (index == -1)
+            return;
+        this._selectedPlacardByIndex(index - 1);
+    },
+
+    _selectedPlacardByIndex: function(index)
+    {
+        if (index < 0 || index >= this.placards.length)
+            return;
+        var placard = this.placards[index];
+        this.selectedCallFrame = placard.callFrame
+    },
+
+    _selectedCallFrameIndex: function()
+    {
+        if (!this._selectedCallFrame)
+            return -1;
+        for (var i = 0; i < this.placards.length; ++i) {
+            var placard = this.placards[i];
+            if (placard.callFrame === this._selectedCallFrame)
+                return i;
+        }
+        return -1;
+    },
+
+    _placardSelected: function(event)
+    {
+        var placardElement = event.target.enclosingNodeOrSelfWithClass("placard");
+        this.selectedCallFrame = placardElement.placard.callFrame;
+    },
+
+    registerShortcuts: function(section)
+    {
+        this._shortcuts = {};
+
+        var nextCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Period,
+            WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+        this._shortcuts[nextCallFrame.key] = this._selectNextCallFrameOnStack.bind(this);
+
+        var prevCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Comma,
+            WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+        this._shortcuts[prevCallFrame.key] = this._selectPreviousCallFrameOnStack.bind(this);
+
+        section.addRelatedKeys([ nextCallFrame.name, prevCallFrame.name ], WebInspector.UIString("Next/previous call frame"));
+    },
+
+    _scriptBreakpointHit: function()
+    {
+        var statusMessageElement = document.createElement("div");
+        statusMessageElement.className = "info";
+        statusMessageElement.appendChild(document.createTextNode(WebInspector.UIString("Paused on a JavaScript breakpoint.")));
+        this.bodyElement.appendChild(statusMessageElement);
+    },
+
+    _nativeBreakpointHit: function(eventData)
+    {
+        var breakpoint = WebInspector.breakpointManager.breakpointViewForEventData(eventData);
+        if (!breakpoint)
+            return;
+
+        var statusMessageElement = document.createElement("div");
+        statusMessageElement.className = "info";
+        breakpoint.populateStatusMessageElement(statusMessageElement, eventData);
+        this.bodyElement.appendChild(statusMessageElement);
+    }
+}
+
+WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Checkbox.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Checkbox.js
new file mode 100644
index 0000000..aed8534
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Checkbox.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Checkbox = function(label, className, tooltip)
+{
+    this.element = document.createElement('label');
+    this._inputElement = document.createElement('input');
+    this._inputElement.type = "checkbox";
+
+    this.element.className = className;
+    this.element.appendChild(this._inputElement);
+    this.element.appendChild(document.createTextNode(label));
+    if (tooltip)
+        this.element.title = tooltip;
+}
+
+WebInspector.Checkbox.prototype = {
+    set checked(checked)
+    {
+        this._inputElement.checked = checked;
+    },
+
+    get checked()
+    {
+        return this._inputElement.checked;
+    },
+
+    addEventListener: function(listener)
+    {
+        function listenerWrapper(event)
+        {
+            if (listener)
+                listener(event);
+            event.stopPropagation();
+            return true;
+        }
+
+        this._inputElement.addEventListener("click", listenerWrapper, false);
+        this.element.addEventListener("click", listenerWrapper, false);
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Color.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Color.js
new file mode 100644
index 0000000..5e7314c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Color.js
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Color = function(str)
+{
+    this.value = str;
+    this._parse();
+}
+
+WebInspector.Color.prototype = {
+    get shorthex()
+    {
+        if ("_short" in this)
+            return this._short;
+
+        if (!this.simple)
+            return null;
+
+        var hex = this.hex;
+        if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5))
+            this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4);
+        else
+            this._short = hex;
+
+        return this._short;
+    },
+
+    get hex()
+    {
+        if (!this.simple)
+            return null;
+
+        return this._hex;
+    },
+
+    set hex(x)
+    {
+        this._hex = x;
+    },
+
+    get rgb()
+    {
+        if ("_rgb" in this)
+            return this._rgb;
+
+        if (this.simple)
+            this._rgb = this._hexToRGB(this.hex);
+        else {
+            var rgba = this.rgba;
+            this._rgb = [rgba[0], rgba[1], rgba[2]];
+        }
+
+        return this._rgb;
+    },
+
+    set rgb(x)
+    {
+        this._rgb = x;
+    },
+
+    get hsl()
+    {
+        if ("_hsl" in this)
+            return this._hsl;
+
+        this._hsl = this._rgbToHSL(this.rgb);
+        return this._hsl;
+    },
+
+    set hsl(x)
+    {
+        this._hsl = x;
+    },
+
+    get nickname()
+    {
+        if (typeof this._nickname !== "undefined") // would be set on parse if there was a nickname
+            return this._nickname;
+        else
+            return null;
+    },
+
+    set nickname(x)
+    {
+        this._nickname = x;
+    },
+
+    get rgba()
+    {
+        return this._rgba;
+    },
+
+    set rgba(x)
+    {
+        this._rgba = x;
+    },
+
+    get hsla()
+    {
+        return this._hsla;
+    },
+
+    set hsla(x)
+    {
+        this._hsla = x;
+    },
+
+    hasShortHex: function()
+    {
+        var shorthex = this.shorthex;
+        return (shorthex && shorthex.length === 3);
+    },
+
+    toString: function(format)
+    {
+        if (!format)
+            format = this.format;
+
+        switch (format) {
+            case "original":
+                return this.value;
+            case "rgb":
+                return "rgb(" + this.rgb.join(", ") + ")";
+            case "rgba":
+                return "rgba(" + this.rgba.join(", ") + ")";
+            case "hsl":
+                var hsl = this.hsl;
+                return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
+            case "hsla":
+                var hsla = this.hsla;
+                return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
+            case "hex":
+                return "#" + this.hex;
+            case "shorthex":
+                return "#" + this.shorthex;
+            case "nickname":
+                return this.nickname;
+        }
+
+        throw "invalid color format";
+    },
+
+    _rgbToHex: function(rgb)
+    {
+        var r = parseInt(rgb[0]).toString(16);
+        var g = parseInt(rgb[1]).toString(16);
+        var b = parseInt(rgb[2]).toString(16);
+        if (r.length === 1)
+            r = "0" + r;
+        if (g.length === 1)
+            g = "0" + g;
+        if (b.length === 1)
+            b = "0" + b;
+
+        return (r + g + b).toUpperCase();
+    },
+
+    _hexToRGB: function(hex)
+    {
+        var r = parseInt(hex.substring(0,2), 16);
+        var g = parseInt(hex.substring(2,4), 16);
+        var b = parseInt(hex.substring(4,6), 16);
+
+        return [r, g, b];
+    },
+
+    _rgbToHSL: function(rgb)
+    {
+        var r = parseInt(rgb[0]) / 255;
+        var g = parseInt(rgb[1]) / 255;
+        var b = parseInt(rgb[2]) / 255;
+        var max = Math.max(r, g, b);
+        var min = Math.min(r, g, b);
+        var diff = max - min;
+        var add = max + min;
+
+        if (min === max)
+            var h = 0;
+        else if (r === max)
+            var h = ((60 * (g - b) / diff) + 360) % 360;
+        else if (g === max)
+            var h = (60 * (b - r) / diff) + 120;
+        else
+            var h = (60 * (r - g) / diff) + 240;
+
+        var l = 0.5 * add;
+
+        if (l === 0)
+            var s = 0;
+        else if (l === 1)
+            var s = 1;
+        else if (l <= 0.5)
+            var s = diff / add;
+        else
+            var s = diff / (2 - add);
+
+        h = Math.round(h);
+        s = Math.round(s*100);
+        l = Math.round(l*100);
+
+        return [h, s, l];
+    },
+
+    _hslToRGB: function(hsl)
+    {
+        var h = parseFloat(hsl[0]) / 360;
+        var s = parseFloat(hsl[1]) / 100;
+        var l = parseFloat(hsl[2]) / 100;
+
+        if (l <= 0.5)
+            var q = l * (1 + s);
+        else
+            var q = l + s - (l * s);
+
+        var p = 2 * l - q;
+
+        var tr = h + (1 / 3);
+        var tg = h;
+        var tb = h - (1 / 3);
+
+        var r = Math.round(hueToRGB(p, q, tr) * 255);
+        var g = Math.round(hueToRGB(p, q, tg) * 255);
+        var b = Math.round(hueToRGB(p, q, tb) * 255);
+        return [r, g, b];
+
+        function hueToRGB(p, q, h) {
+            if (h < 0)
+                h += 1;
+            else if (h > 1)
+                h -= 1;
+
+            if ((h * 6) < 1)
+                return p + (q - p) * h * 6;
+            else if ((h * 2) < 1)
+                return q;
+            else if ((h * 3) < 2)
+                return p + (q - p) * ((2 / 3) - h) * 6;
+            else
+                return p;
+        }
+    },
+
+    _rgbaToHSLA: function(rgba)
+    {
+        var alpha = rgba[3];
+        var hsl = this._rgbToHSL(rgba)
+        hsl.push(alpha);
+        return hsl;
+    },
+
+    _hslaToRGBA: function(hsla)
+    {
+        var alpha = hsla[3];
+        var rgb = this._hslToRGB(hsla);
+        rgb.push(alpha);
+        return rgb;
+    },
+
+    _parse: function()
+    {
+        // Special Values - Advanced but Must Be Parsed First - transparent
+        var value = this.value.toLowerCase().replace(/%|\s+/g, "");
+        if (value in WebInspector.Color.AdvancedNickNames) {
+            this.format = "nickname";
+            var set = WebInspector.Color.AdvancedNickNames[value];
+            this.simple = false;
+            this.rgba = set[0];
+            this.hsla = set[1];
+            this.nickname = set[2];
+            this.alpha = set[0][3];
+            return;
+        }
+
+        // Simple - #hex, rgb(), nickname, hsl()
+        var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i;
+        var match = this.value.match(simple);
+        if (match) {
+            this.simple = true;
+
+            if (match[1]) { // hex
+                var hex = match[1].toUpperCase();
+                if (hex.length === 3) {
+                    this.format = "shorthex";
+                    this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
+                } else {
+                    this.format = "hex";
+                    this.hex = hex;
+                }
+            } else if (match[2]) { // rgb
+                this.format = "rgb";
+                var rgb = match[2].split(/\s*,\s*/);
+                this.rgb = rgb;
+                this.hex = this._rgbToHex(rgb);
+            } else if (match[3]) { // nickname
+                var nickname = match[3].toLowerCase();
+                if (nickname in WebInspector.Color.Nicknames) {
+                    this.format = "nickname";
+                    this.hex = WebInspector.Color.Nicknames[nickname];
+                } else // unknown name
+                    throw "unknown color name";
+            } else if (match[4]) { // hsl
+                this.format = "hsl";
+                var hsl = match[4].replace(/%/g, "").split(/\s*,\s*/);
+                this.hsl = hsl;
+                this.rgb = this._hslToRGB(hsl);
+                this.hex = this._rgbToHex(this.rgb);
+            }
+
+            // Fill in the values if this is a known hex color
+            var hex = this.hex;
+            if (hex && hex in WebInspector.Color.HexTable) {
+                var set = WebInspector.Color.HexTable[hex];
+                this.rgb = set[0];
+                this.hsl = set[1];
+                this.nickname = set[2];
+            }
+
+            return;
+        }
+
+        // Advanced - rgba(), hsla()
+        var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/;
+        match = this.value.match(advanced);
+        if (match) {
+            this.simple = false;
+            if (match[1]) { // rgba
+                this.format = "rgba";
+                this.rgba = match[1].split(/\s*,\s*/);
+                this.hsla = this._rgbaToHSLA(this.rgba);
+                this.alpha = this.rgba[3];
+            } else if (match[2]) { // hsla
+                this.format = "hsla";
+                this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/);
+                this.rgba = this._hslaToRGBA(this.hsla);
+                this.alpha = this.hsla[3];
+            }
+
+            return;
+        }
+
+        // Could not parse as a valid color
+        throw "could not parse color";
+    }
+}
+
+// Simple Values: [rgb, hsl, nickname]
+WebInspector.Color.HexTable = {
+    "000000": [[0, 0, 0], [0, 0, 0], "black"],
+    "000080": [[0, 0, 128], [240, 100, 25], "navy"],
+    "00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"],
+    "0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"],
+    "0000FF": [[0, 0, 255], [240, 100, 50], "blue"],
+    "006400": [[0, 100, 0], [120, 100, 20], "darkGreen"],
+    "008000": [[0, 128, 0], [120, 100, 25], "green"],
+    "008080": [[0, 128, 128], [180, 100, 25], "teal"],
+    "008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"],
+    "00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"],
+    "00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"],
+    "00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"],
+    "00FF00": [[0, 255, 0], [120, 100, 50], "lime"],
+    "00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"],
+    "00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"],
+    "191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"],
+    "1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"],
+    "20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"],
+    "228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"],
+    "2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"],
+    "2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"],
+    "32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"],
+    "3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"],
+    "40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"],
+    "4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"],
+    "4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"],
+    "483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"],
+    "48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"],
+    "4B0082": [[75, 0, 130], [275, 100, 25], "indigo"],
+    "556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"],
+    "5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"],
+    "6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"],
+    "66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"],
+    "696969": [[105, 105, 105], [0, 0, 41], "dimGray"],
+    "6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"],
+    "6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"],
+    "708090": [[112, 128, 144], [210, 13, 50], "slateGray"],
+    "778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"],
+    "7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"],
+    "7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"],
+    "7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"],
+    "7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"],
+    "800000": [[128, 0, 0], [0, 100, 25], "maroon"],
+    "800080": [[128, 0, 128], [300, 100, 25], "purple"],
+    "808000": [[128, 128, 0], [60, 100, 25], "olive"],
+    "808080": [[128, 128, 128], [0, 0, 50], "gray"],
+    "87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"],
+    "87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"],
+    "8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"],
+    "8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"],
+    "8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"],
+    "8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"],
+    "8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"],
+    "90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"],
+    "9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"],
+    "9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"],
+    "98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"],
+    "9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"],
+    "9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"],
+    "A0522D": [[160, 82, 45], [19, 56, 40], "sienna"],
+    "A52A2A": [[165, 42, 42], [0, 59, 41], "brown"],
+    "A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"],
+    "ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"],
+    "ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"],
+    "AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"],
+    "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"],
+    "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"],
+    "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"],
+    "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenrod"],
+    "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"],
+    "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"],
+    "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"],
+    "C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"],
+    "C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"],
+    "CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"],
+    "CD853F": [[205, 133, 63], [30, 59, 53], "peru"],
+    "D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"],
+    "D2B48C": [[210, 180, 140], [34, 44, 69], "tan"],
+    "D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"],
+    "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"],
+    "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"],
+    "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"],
+    "DAA520": [[218, 165, 32], [43, 74, 49], "goldenrod"],
+    "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"],
+    "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"],
+    "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"],
+    "DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"],
+    "E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"],
+    "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"],
+    "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"],
+    "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"],
+    "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenrod"],
+    "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"],
+    "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"],
+    "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"],
+    "F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"],
+    "F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"],
+    "F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"],
+    "F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"],
+    "F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"],
+    "F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"],
+    "F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"],
+    "F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"],
+    "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"],
+    "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"],
+    "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"],
+    "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenrodYellow"],
+    "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"],
+    "FF0000": [[255, 0, 0], [0, 100, 50], "red"],
+    "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"],
+    "FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"],
+    "FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"],
+    "FF6347": [[255, 99, 71], [9, 100, 64], "tomato"],
+    "FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"],
+    "FF7F50": [[255, 127, 80], [16, 100, 66], "coral"],
+    "FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"],
+    "FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"],
+    "FFA500": [[255, 165, 0], [39, 100, 50], "orange"],
+    "FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"],
+    "FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"],
+    "FFD700": [[255, 215, 0], [51, 100, 50], "gold"],
+    "FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"],
+    "FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"],
+    "FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"],
+    "FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"],
+    "FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"],
+    "FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"],
+    "FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"],
+    "FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"],
+    "FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"],
+    "FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"],
+    "FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"],
+    "FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"],
+    "FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"],
+    "FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"],
+    "FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"],
+    "FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"],
+    "FFFFFF": [[255, 255, 255], [0, 100, 100], "white"]
+};
+
+// Simple Values
+WebInspector.Color.Nicknames = {
+    "aliceblue": "F0F8FF",
+    "antiquewhite": "FAEBD7",
+    "aqua": "00FFFF",
+    "aquamarine": "7FFFD4",
+    "azure": "F0FFFF",
+    "beige": "F5F5DC",
+    "bisque": "FFE4C4",
+    "black": "000000",
+    "blanchedalmond": "FFEBCD",
+    "blue": "0000FF",
+    "blueviolet": "8A2BE2",
+    "brown": "A52A2A",
+    "burlywood": "DEB887",
+    "cadetblue": "5F9EA0",
+    "chartreuse": "7FFF00",
+    "chocolate": "D2691E",
+    "coral": "FF7F50",
+    "cornflowerblue": "6495ED",
+    "cornsilk": "FFF8DC",
+    "crimson": "DC143C",
+    "cyan": "00FFFF",
+    "darkblue": "00008B",
+    "darkcyan": "008B8B",
+    "darkgoldenrod": "B8860B",
+    "darkgray": "A9A9A9",
+    "darkgreen": "006400",
+    "darkkhaki": "BDB76B",
+    "darkmagenta": "8B008B",
+    "darkolivegreen": "556B2F",
+    "darkorange": "FF8C00",
+    "darkorchid": "9932CC",
+    "darkred": "8B0000",
+    "darksalmon": "E9967A",
+    "darkseagreen": "8FBC8F",
+    "darkslateblue": "483D8B",
+    "darkslategray": "2F4F4F",
+    "darkturquoise": "00CED1",
+    "darkviolet": "9400D3",
+    "deeppink": "FF1493",
+    "deepskyblue": "00BFFF",
+    "dimgray": "696969",
+    "dodgerblue": "1E90FF",
+    "firebrick": "B22222",
+    "floralwhite": "FFFAF0",
+    "forestgreen": "228B22",
+    "fuchsia": "FF00FF",
+    "gainsboro": "DCDCDC",
+    "ghostwhite": "F8F8FF",
+    "gold": "FFD700",
+    "goldenrod": "DAA520",
+    "gray": "808080",
+    "green": "008000",
+    "greenyellow": "ADFF2F",
+    "honeydew": "F0FFF0",
+    "hotpink": "FF69B4",
+    "indianred": "CD5C5C",
+    "indigo": "4B0082",
+    "ivory": "FFFFF0",
+    "khaki": "F0E68C",
+    "lavender": "E6E6FA",
+    "lavenderblush": "FFF0F5",
+    "lawngreen": "7CFC00",
+    "lemonchiffon": "FFFACD",
+    "lightblue": "ADD8E6",
+    "lightcoral": "F08080",
+    "lightcyan": "E0FFFF",
+    "lightgoldenrodyellow": "FAFAD2",
+    "lightgreen": "90EE90",
+    "lightgrey": "D3D3D3",
+    "lightpink": "FFB6C1",
+    "lightsalmon": "FFA07A",
+    "lightseagreen": "20B2AA",
+    "lightskyblue": "87CEFA",
+    "lightslategray": "778899",
+    "lightsteelblue": "B0C4DE",
+    "lightyellow": "FFFFE0",
+    "lime": "00FF00",
+    "limegreen": "32CD32",
+    "linen": "FAF0E6",
+    "magenta": "FF00FF",
+    "maroon": "800000",
+    "mediumaquamarine": "66CDAA",
+    "mediumblue": "0000CD",
+    "mediumorchid": "BA55D3",
+    "mediumpurple": "9370D8",
+    "mediumseagreen": "3CB371",
+    "mediumslateblue": "7B68EE",
+    "mediumspringgreen": "00FA9A",
+    "mediumturquoise": "48D1CC",
+    "mediumvioletred": "C71585",
+    "midnightblue": "191970",
+    "mintcream": "F5FFFA",
+    "mistyrose": "FFE4E1",
+    "moccasin": "FFE4B5",
+    "navajowhite": "FFDEAD",
+    "navy": "000080",
+    "oldlace": "FDF5E6",
+    "olive": "808000",
+    "olivedrab": "6B8E23",
+    "orange": "FFA500",
+    "orangered": "FF4500",
+    "orchid": "DA70D6",
+    "palegoldenrod": "EEE8AA",
+    "palegreen": "98FB98",
+    "paleturquoise": "AFEEEE",
+    "palevioletred": "D87093",
+    "papayawhip": "FFEFD5",
+    "peachpuff": "FFDAB9",
+    "peru": "CD853F",
+    "pink": "FFC0CB",
+    "plum": "DDA0DD",
+    "powderblue": "B0E0E6",
+    "purple": "800080",
+    "red": "FF0000",
+    "rosybrown": "BC8F8F",
+    "royalblue": "4169E1",
+    "saddlebrown": "8B4513",
+    "salmon": "FA8072",
+    "sandybrown": "F4A460",
+    "seagreen": "2E8B57",
+    "seashell": "FFF5EE",
+    "sienna": "A0522D",
+    "silver": "C0C0C0",
+    "skyblue": "87CEEB",
+    "slateblue": "6A5ACD",
+    "slategray": "708090",
+    "snow": "FFFAFA",
+    "springgreen": "00FF7F",
+    "steelblue": "4682B4",
+    "tan": "D2B48C",
+    "teal": "008080",
+    "thistle": "D8BFD8",
+    "tomato": "FF6347",
+    "turquoise": "40E0D0",
+    "violet": "EE82EE",
+    "wheat": "F5DEB3",
+    "white": "FFFFFF",
+    "whitesmoke": "F5F5F5",
+    "yellow": "FFFF00",
+    "yellowgreen": "9ACD32"
+};
+
+// Advanced Values [rgba, hsla, nickname]
+WebInspector.Color.AdvancedNickNames = {
+    "transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+    "rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+    "hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsolePanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsolePanel.js
new file mode 100644
index 0000000..5a0c2e7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsolePanel.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ConsolePanel = function()
+{
+    WebInspector.Panel.call(this, "console");
+}
+
+WebInspector.ConsolePanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Console");
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+
+        this._previousConsoleState = WebInspector.drawer.state;
+        WebInspector.drawer.enterPanelMode();
+        WebInspector.showConsole();
+        
+        // Move the scope bar to the top of the messages, like the resources filter.
+        var scopeBar = document.getElementById("console-filter");
+        var consoleMessages = document.getElementById("console-messages");
+
+        scopeBar.parentNode.removeChild(scopeBar);
+        document.getElementById("console-view").insertBefore(scopeBar, consoleMessages);
+        
+        // Update styles, and give console-messages a top margin so it doesn't overwrite the scope bar.
+        scopeBar.addStyleClass("console-filter-top");
+        scopeBar.removeStyleClass("status-bar-item");
+
+        consoleMessages.addStyleClass("console-filter-top");
+    },
+
+    hide: function()
+    {
+        WebInspector.Panel.prototype.hide.call(this);
+
+        if (this._previousConsoleState === WebInspector.Drawer.State.Hidden)
+            WebInspector.drawer.immediatelyExitPanelMode();
+        else
+            WebInspector.drawer.exitPanelMode();
+        delete this._previousConsoleState;
+        
+        // Move the scope bar back to the bottom bar, next to Clear Console.
+        var scopeBar = document.getElementById("console-filter");
+
+        scopeBar.parentNode.removeChild(scopeBar);
+        document.getElementById("other-drawer-status-bar-items").appendChild(scopeBar);
+        
+        // Update styles, and remove the top margin on console-messages.
+        scopeBar.removeStyleClass("console-filter-top");
+        scopeBar.addStyleClass("status-bar-item");
+
+        document.getElementById("console-messages").removeStyleClass("console-filter-top");
+    }
+}
+
+WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsoleView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsoleView.js
new file mode 100644
index 0000000..35d1ebf
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ConsoleView.js
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>";
+
+WebInspector.ConsoleView = function(drawer)
+{
+    WebInspector.View.call(this, document.getElementById("console-view"));
+
+    this.messages = [];
+    this.drawer = drawer;
+
+    this.clearButton = document.getElementById("clear-console-status-bar-item");
+    this.clearButton.title = WebInspector.UIString("Clear console log.");
+    this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
+
+    this.messagesElement = document.getElementById("console-messages");
+    this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false);
+    this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true);
+
+    this.promptElement = document.getElementById("console-prompt");
+    this.promptElement.className = "source-code";
+    this.promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
+    this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), ExpressionStopCharacters + ".");
+    this.prompt.history = WebInspector.settings.consoleHistory;
+
+    this.topGroup = new WebInspector.ConsoleGroup(null);
+    this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
+    this.currentGroup = this.topGroup;
+
+    this.toggleConsoleButton = document.getElementById("console-status-bar-item");
+    this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
+    this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false);
+
+    // Will hold the list of filter elements
+    this.filterBarElement = document.getElementById("console-filter");
+
+    function createDividerElement() {
+        var dividerElement = document.createElement("div");
+        dividerElement.addStyleClass("scope-bar-divider");
+        this.filterBarElement.appendChild(dividerElement);
+    }
+
+    var updateFilterHandler = this._updateFilter.bind(this);
+    function createFilterElement(category, label) {
+        var categoryElement = document.createElement("li");
+        categoryElement.category = category;
+        categoryElement.className = category;
+        categoryElement.addEventListener("click", updateFilterHandler, false);
+        categoryElement.textContent = label;
+
+        this.filterBarElement.appendChild(categoryElement);
+
+        return categoryElement;
+    }
+
+    this.allElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));
+    createDividerElement.call(this);
+    this.errorElement = createFilterElement.call(this, "errors", WebInspector.UIString("Errors"));
+    this.warningElement = createFilterElement.call(this, "warnings", WebInspector.UIString("Warnings"));
+    this.logElement = createFilterElement.call(this, "logs", WebInspector.UIString("Logs"));
+
+    this.filter(this.allElement, false);
+    this._registerShortcuts();
+
+    this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);
+
+    this._customFormatters = {
+        "object": this._formatobject,
+        "array":  this._formatarray,
+        "node":   this._formatnode,
+        "string": this._formatstring
+    };
+
+    this._registerConsoleDomainDispatcher();
+}
+
+WebInspector.ConsoleView.prototype = {
+    _registerConsoleDomainDispatcher: function() {
+        var console = this;
+        var dispatcher = {
+            addConsoleMessage: function(payload)
+            {
+                var consoleMessage = new WebInspector.ConsoleMessage(
+                    payload.source,
+                    payload.type,
+                    payload.level,
+                    payload.line,
+                    payload.url,
+                    payload.repeatCount,
+                    payload.message,
+                    payload.parameters,
+                    payload.stackTrace,
+                    payload.requestId);
+                console.addMessage(consoleMessage);
+            },
+
+            updateConsoleMessageExpiredCount: function(count)
+            {
+                var message = String.sprintf(WebInspector.UIString("%d console messages are not shown."), count);
+                console.addMessage(WebInspector.ConsoleMessage.createTextMessage(message, WebInspector.ConsoleMessage.MessageLevel.Warning));
+            },
+
+            updateConsoleMessageRepeatCount: function(count)
+            {
+                var msg = console.previousMessage;
+                var prevRepeatCount = msg.totalRepeatCount;
+
+                if (!console.commandSincePreviousMessage) {
+                    msg.repeatDelta = count - prevRepeatCount;
+                    msg.repeatCount = msg.repeatCount + msg.repeatDelta;
+                    msg.totalRepeatCount = count;
+                    msg._updateRepeatCount();
+                    console._incrementErrorWarningCount(msg);
+                } else {
+                    var msgCopy = new WebInspector.ConsoleMessage(msg.source, msg.type, msg.level, msg.line, msg.url, count - prevRepeatCount, msg._messageText, msg._parameters, msg._stackTrace, msg._requestId);
+                    msgCopy.totalRepeatCount = count;
+                    msgCopy._formatMessage();
+                    console.addMessage(msgCopy);
+                }
+            },
+
+            consoleMessagesCleared: function()
+            {
+                console.clearMessages();
+            },
+        }
+        InspectorBackend.registerDomainDispatcher("Console", dispatcher);
+    },
+
+    _updateFilter: function(e)
+    {
+        var isMac = WebInspector.isMac();
+        var selectMultiple = false;
+        if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+        if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+
+        this.filter(e.target, selectMultiple);
+    },
+
+    filter: function(target, selectMultiple)
+    {
+        function unselectAll()
+        {
+            this.allElement.removeStyleClass("selected");
+            this.errorElement.removeStyleClass("selected");
+            this.warningElement.removeStyleClass("selected");
+            this.logElement.removeStyleClass("selected");
+
+            this.messagesElement.removeStyleClass("filter-all");
+            this.messagesElement.removeStyleClass("filter-errors");
+            this.messagesElement.removeStyleClass("filter-warnings");
+            this.messagesElement.removeStyleClass("filter-logs");
+        }
+
+        var targetFilterClass = "filter-" + target.category;
+
+        if (target.category === "all") {
+            if (target.hasStyleClass("selected")) {
+                // We can't unselect all, so we break early here
+                return;
+            }
+
+            unselectAll.call(this);
+        } else {
+            // Something other than all is being selected, so we want to unselect all
+            if (this.allElement.hasStyleClass("selected")) {
+                this.allElement.removeStyleClass("selected");
+                this.messagesElement.removeStyleClass("filter-all");
+            }
+        }
+
+        if (!selectMultiple) {
+            // If multiple selection is off, we want to unselect everything else
+            // and just select ourselves.
+            unselectAll.call(this);
+
+            target.addStyleClass("selected");
+            this.messagesElement.addStyleClass(targetFilterClass);
+
+            return;
+        }
+
+        if (target.hasStyleClass("selected")) {
+            // If selectMultiple is turned on, and we were selected, we just
+            // want to unselect ourselves.
+            target.removeStyleClass("selected");
+            this.messagesElement.removeStyleClass(targetFilterClass);
+        } else {
+            // If selectMultiple is turned on, and we weren't selected, we just
+            // want to select ourselves.
+            target.addStyleClass("selected");
+            this.messagesElement.addStyleClass(targetFilterClass);
+        }
+    },
+
+    _toggleConsoleButtonClicked: function()
+    {
+        this.drawer.visibleView = this;
+    },
+
+    attach: function(mainElement, statusBarElement)
+    {
+        mainElement.appendChild(this.element);
+        statusBarElement.appendChild(this.clearButton);
+        statusBarElement.appendChild(this.filterBarElement);
+    },
+
+    show: function()
+    {
+        this.toggleConsoleButton.addStyleClass("toggled-on");
+        this.toggleConsoleButton.title = WebInspector.UIString("Hide console.");
+        if (!this.prompt.isCaretInsidePrompt())
+            this.prompt.moveCaretToEndOfPrompt();
+    },
+
+    afterShow: function()
+    {
+        WebInspector.currentFocusElement = this.promptElement;
+    },
+
+    hide: function()
+    {
+        this.toggleConsoleButton.removeStyleClass("toggled-on");
+        this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
+    },
+
+    _scheduleScrollIntoView: function()
+    {
+        if (this._scrollIntoViewTimer)
+            return;
+
+        function scrollIntoView()
+        {
+            this.promptElement.scrollIntoView(true);
+            delete this._scrollIntoViewTimer;
+        }
+        this._scrollIntoViewTimer = setTimeout(scrollIntoView.bind(this), 20);
+    },
+
+    addMessage: function(msg)
+    {
+        var shouldScrollToLastMessage = this.messagesElement.isScrolledToBottom();
+
+        if (msg instanceof WebInspector.ConsoleMessage && !(msg instanceof WebInspector.ConsoleCommandResult)) {
+            this._incrementErrorWarningCount(msg);
+            WebInspector.resourceTreeModel.addConsoleMessage(msg);
+            WebInspector.panels.scripts.addConsoleMessage(msg);
+            this.commandSincePreviousMessage = false;
+            this.previousMessage = msg;
+        } else if (msg instanceof WebInspector.ConsoleCommand) {
+            if (this.previousMessage) {
+                this.commandSincePreviousMessage = true;
+            }
+        }
+
+        this.messages.push(msg);
+
+        if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) {
+            var parentGroup = this.currentGroup.parentGroup
+            if (parentGroup)
+                this.currentGroup = parentGroup;
+        } else {
+            if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) {
+                var group = new WebInspector.ConsoleGroup(this.currentGroup);
+                this.currentGroup.messagesElement.appendChild(group.element);
+                this.currentGroup = group;
+            }
+
+            this.currentGroup.addMessage(msg);
+        }
+
+        if (shouldScrollToLastMessage)
+            this._scheduleScrollIntoView();
+    },
+
+    _incrementErrorWarningCount: function(msg)
+    {
+        switch (msg.level) {
+            case WebInspector.ConsoleMessage.MessageLevel.Warning:
+                WebInspector.warnings += msg.repeatDelta;
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Error:
+                WebInspector.errors += msg.repeatDelta;
+                break;
+        }
+    },
+
+    requestClearMessages: function()
+    {
+        InspectorBackend.clearConsoleMessages();
+    },
+
+    clearMessages: function()
+    {
+        WebInspector.resourceTreeModel.clearConsoleMessages();
+        WebInspector.panels.scripts.clearConsoleMessages();
+
+        this.messages = [];
+
+        this.currentGroup = this.topGroup;
+        this.topGroup.messagesElement.removeChildren();
+
+        WebInspector.errors = 0;
+        WebInspector.warnings = 0;
+
+        delete this.commandSincePreviousMessage;
+        delete this.previousMessage;
+    },
+
+    completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
+    {
+        // Pass less stop characters to rangeOfWord so the range will be a more complete expression.
+        var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, ExpressionStopCharacters, this.promptElement, "backward");
+        var expressionString = expressionRange.toString();
+        var lastIndex = expressionString.length - 1;
+
+        var dotNotation = (expressionString[lastIndex] === ".");
+        var bracketNotation = (expressionString[lastIndex] === "[");
+
+        if (dotNotation || bracketNotation)
+            expressionString = expressionString.substr(0, lastIndex);
+
+        var prefix = wordRange.toString();
+        if (!expressionString && !prefix)
+            return;
+
+        var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix);
+        // Collect comma separated object properties for the completion.
+
+        var includeCommandLineAPI = (!dotNotation && !bracketNotation);
+        var injectedScriptAccess;
+        if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+            InspectorBackend.getCompletionsOnCallFrame(WebInspector.panels.scripts.selectedCallFrameId(), expressionString, includeCommandLineAPI, reportCompletions);
+        else
+            InspectorBackend.getCompletions(expressionString, includeCommandLineAPI, reportCompletions);
+    },
+
+    _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) {
+        if (isException)
+            return;
+
+        if (bracketNotation) {
+            if (prefix.length && prefix[0] === "'")
+                var quoteUsed = "'";
+            else
+                var quoteUsed = "\"";
+        }
+
+        var results = [];
+        var properties = Object.keys(result).sort();
+
+        for (var i = 0; i < properties.length; ++i) {
+            var property = properties[i];
+
+            if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property))
+                continue;
+
+            if (bracketNotation) {
+                if (!/^[0-9]+$/.test(property))
+                    property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed;
+                property += "]";
+            }
+
+            if (property.length < prefix.length)
+                continue;
+            if (property.indexOf(prefix) !== 0)
+                continue;
+
+            results.push(property);
+            if (bestMatchOnly)
+                break;
+        }
+        completionsReadyCallback(results);
+    },
+
+    _clearButtonClicked: function()
+    {
+        this.requestClearMessages();
+    },
+
+    _handleContextMenuEvent: function(event)
+    {
+        if (!window.getSelection().isCollapsed) {
+            // If there is a selection, we want to show our normal context menu
+            // (with Copy, etc.), and not Clear Console.
+            return;
+        }
+
+        var itemAction = function () {
+            WebInspector.settings.monitoringXHREnabled = !WebInspector.settings.monitoringXHREnabled;
+            InspectorBackend.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
+        }.bind(this);
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendCheckboxItem(WebInspector.UIString("XMLHttpRequest logging"), itemAction, WebInspector.settings.monitoringXHREnabled)
+        contextMenu.appendItem(WebInspector.UIString("Clear Console"), this.requestClearMessages.bind(this));
+        contextMenu.show(event);
+    },
+
+    _messagesSelectStart: function(event)
+    {
+        if (this._selectionTimeout)
+            clearTimeout(this._selectionTimeout);
+
+        this.prompt.clearAutoComplete();
+
+        function moveBackIfOutside()
+        {
+            delete this._selectionTimeout;
+            if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+                this.prompt.moveCaretToEndOfPrompt();
+            this.prompt.autoCompleteSoon();
+        }
+
+        this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+    },
+
+    _messagesClicked: function(event)
+    {
+        var link = event.target.enclosingNodeOrSelfWithNodeName("a");
+        if (!link || !link.representedNode)
+            return;
+
+        WebInspector.updateFocusedNode(link.representedNode.id);
+        event.stopPropagation();
+        event.preventDefault();
+    },
+
+    _registerShortcuts: function()
+    {
+        this._shortcuts = {};
+
+        var shortcut = WebInspector.KeyboardShortcut;
+        var shortcutK = shortcut.makeDescriptor("k", WebInspector.KeyboardShortcut.Modifiers.Meta);
+        // This case requires a separate bound function as its isMacOnly property should not be shared among different shortcut handlers.
+        this._shortcuts[shortcutK.key] = this.requestClearMessages.bind(this);
+        this._shortcuts[shortcutK.key].isMacOnly = true;
+
+        var clearConsoleHandler = this.requestClearMessages.bind(this);
+        var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+        this._shortcuts[shortcutL.key] = clearConsoleHandler;
+
+        var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Console"));
+        var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ];
+        section.addAlternateKeys(keys, WebInspector.UIString("Clear Console"));
+
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.Tab),
+            shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Next/previous suggestion"));
+        section.addKey(shortcut.shortcutToString(shortcut.Keys.Right), WebInspector.UIString("Accept suggestion"));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.Down),
+            shortcut.shortcutToString(shortcut.Keys.Up)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Next/previous line"));
+        keys = [
+            shortcut.shortcutToString("N", shortcut.Modifiers.Alt),
+            shortcut.shortcutToString("P", shortcut.Modifiers.Alt)
+        ];
+        if (WebInspector.isMac())
+            section.addRelatedKeys(keys, WebInspector.UIString("Next/previous command"));
+        section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Execute command"));
+    },
+
+    _promptKeyDown: function(event)
+    {
+        if (isEnterKey(event)) {
+            this._enterKeyPressed(event);
+            return;
+        }
+
+        var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+        var handler = this._shortcuts[shortcut];
+        if (handler) {
+            if (!this._shortcuts[shortcut].isMacOnly || WebInspector.isMac()) {
+                handler();
+                event.preventDefault();
+                return;
+            }
+        }
+    },
+
+    evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, callback)
+    {
+        if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
+            WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, objectGroup, includeCommandLineAPI, callback);
+            return;
+        }
+
+        if (!expression) {
+            // There is no expression, so the completion should happen against global properties.
+            expression = "this";
+        }
+
+        function evalCallback(result)
+        {
+            callback(WebInspector.RemoteObject.fromPayload(result));
+        }
+        InspectorBackend.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
+    },
+
+    _enterKeyPressed: function(event)
+    {
+        if (event.altKey || event.ctrlKey || event.shiftKey)
+            return;
+
+        event.preventDefault();
+        event.stopPropagation();
+
+        this.prompt.clearAutoComplete(true);
+
+        var str = this.prompt.text;
+        if (!str.length)
+            return;
+
+        var commandMessage = new WebInspector.ConsoleCommand(str);
+        this.addMessage(commandMessage);
+
+        var self = this;
+        function printResult(result)
+        {
+            self.prompt.history.push(str);
+            self.prompt.historyOffset = 0;
+            self.prompt.text = "";
+
+            WebInspector.settings.consoleHistory = self.prompt.history.slice(-30);
+
+            self.addMessage(new WebInspector.ConsoleCommandResult(result, commandMessage));
+        }
+        this.evalInInspectedWindow(str, "console", true, printResult);
+    },
+
+    _format: function(output, forceObjectFormat)
+    {
+        var isProxy = (output != null && typeof output === "object");
+        var type = (forceObjectFormat ? "object" : WebInspector.RemoteObject.type(output));
+
+        var formatter = this._customFormatters[type];
+        if (!formatter || !isProxy) {
+            formatter = this._formatvalue;
+            output = output.description;
+        }
+
+        var span = document.createElement("span");
+        span.className = "console-formatted-" + type + " source-code";
+        formatter.call(this, output, span);
+        return span;
+    },
+
+    _formatvalue: function(val, elem)
+    {
+        elem.appendChild(document.createTextNode(val));
+    },
+
+    _formatobject: function(obj, elem)
+    {
+        elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element);
+    },
+
+    _formatnode: function(object, elem)
+    {
+        function printNode(nodeId)
+        {
+            if (!nodeId) {
+                // Sometimes DOM is loaded after the sync message is being formatted, so we get no
+                // nodeId here. So we fall back to object formatting here.
+                this._formatobject(object, elem);
+                return;
+            }
+            var treeOutline = new WebInspector.ElementsTreeOutline();
+            treeOutline.showInElementsPanelEnabled = true;
+            treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId);
+            treeOutline.element.addStyleClass("outline-disclosure");
+            if (!treeOutline.children[0].hasChildren)
+                treeOutline.element.addStyleClass("single-node");
+            elem.appendChild(treeOutline.element);
+        }
+        object.pushNodeToFrontend(printNode.bind(this));
+    },
+
+    _formatarray: function(arr, elem)
+    {
+        arr.getOwnProperties(false, this._printArray.bind(this, elem));
+    },
+
+    _formatstring: function(output, elem)
+    {
+        var span = document.createElement("span");
+        span.className = "console-formatted-string source-code";
+        span.appendChild(WebInspector.linkifyStringAsFragment(output.description));
+
+        // Make black quotes.
+        elem.removeStyleClass("console-formatted-string");
+        elem.appendChild(document.createTextNode("\""));
+        elem.appendChild(span);
+        elem.appendChild(document.createTextNode("\""));
+    },
+
+    _printArray: function(elem, properties)
+    {
+        if (!properties)
+            return;
+
+        var elements = [];
+        for (var i = 0; i < properties.length; ++i) {
+            var name = properties[i].name;
+            if (name == parseInt(name))
+                elements[name] = this._formatAsArrayEntry(properties[i].value);
+        }
+
+        elem.appendChild(document.createTextNode("["));
+        for (var i = 0; i < elements.length; ++i) {
+            var element = elements[i];
+            if (element)
+                elem.appendChild(element);
+            else
+                elem.appendChild(document.createTextNode("undefined"))
+            if (i < elements.length - 1)
+                elem.appendChild(document.createTextNode(", "));
+        }
+        elem.appendChild(document.createTextNode("]"));
+    },
+
+    _formatAsArrayEntry: function(output)
+    {
+        // Prevent infinite expansion of cross-referencing arrays.
+        return this._format(output, WebInspector.RemoteObject.type(output) === "array");
+    }
+}
+
+WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.ConsoleMessage = function(source, type, level, line, url, repeatCount, message, parameters, stackTrace, requestId)
+{
+    this.source = source;
+    this.type = type;
+    this.level = level;
+    this.line = line;
+    this.url = url;
+    this.repeatCount = repeatCount;
+    this.repeatDelta = repeatCount;
+    this.totalRepeatCount = repeatCount;
+    this._messageText = message;
+    this._parameters = parameters;
+    this._stackTrace = stackTrace;
+    this._requestId = requestId;
+
+    if (stackTrace && stackTrace.length) {
+        var topCallFrame = stackTrace[0];
+        if (!this.url)
+            this.url = topCallFrame.scriptName;
+        if (!this.line)
+            this.line = topCallFrame.lineNumber;
+    }
+
+    this._formatMessage();
+}
+
+WebInspector.ConsoleMessage.createTextMessage = function(text, level)
+{
+    level = level || WebInspector.ConsoleMessage.MessageLevel.Log;
+    return new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, 0, null, 1, null, [text], null);
+}
+
+WebInspector.ConsoleMessage.prototype = {
+    _formatMessage: function()
+    {
+        var stackTrace = this._stackTrace;
+        var messageText;
+        switch (this.type) {
+            case WebInspector.ConsoleMessage.MessageType.Trace:
+                messageText = document.createTextNode("console.trace()");
+                break;
+            case WebInspector.ConsoleMessage.MessageType.UncaughtException:
+                messageText = document.createTextNode(this._messageText);
+                break;
+            case WebInspector.ConsoleMessage.MessageType.NetworkError:
+                var resource = this._requestId && WebInspector.networkResourceById(this._requestId);
+                if (resource) {
+                    stackTrace = resource.stackTrace;
+
+                    messageText = document.createElement("span");
+                    messageText.appendChild(document.createTextNode(resource.requestMethod + " "));
+                    messageText.appendChild(WebInspector.linkifyURLAsNode(resource.url));
+                    if (resource.failed)
+                        messageText.appendChild(document.createTextNode(" " + resource.localizedFailDescription));
+                    else
+                        messageText.appendChild(document.createTextNode(" " + resource.statusCode + " (" + resource.statusText + ")"));
+                } else
+                    messageText = this._format([this._messageText]);
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Assert:
+                var args = [WebInspector.UIString("Assertion failed:")];
+                if (this._parameters)
+                    args = args.concat(this._parameters);
+                messageText = this._format(args);
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Object:
+                var obj = this._parameters ? this._parameters[0] : undefined;
+                var args = ["%O", obj];
+                messageText = this._format(args);
+                break;
+            default:
+                var args = this._parameters || [this._messageText];
+                messageText = this._format(args);
+                break;
+        }
+
+        this._formattedMessage = document.createElement("span");
+        this._formattedMessage.className = "console-message-text source-code";
+
+        if (this.url && this.url !== "undefined") {
+            var urlElement = WebInspector.linkifyResourceAsNode(this.url, "scripts", this.line, "console-message-url");
+            this._formattedMessage.appendChild(urlElement);
+        }
+
+        this._formattedMessage.appendChild(messageText);
+
+        if (this._stackTrace) {
+            switch (this.type) {
+                case WebInspector.ConsoleMessage.MessageType.Trace:
+                case WebInspector.ConsoleMessage.MessageType.UncaughtException:
+                case WebInspector.ConsoleMessage.MessageType.NetworkError:
+                case WebInspector.ConsoleMessage.MessageType.Assert: {
+                    var ol = document.createElement("ol");
+                    ol.className = "outline-disclosure";
+                    var treeOutline = new TreeOutline(ol);
+
+                    var content = this._formattedMessage;
+                    var root = new TreeElement(content, null, true);
+                    content.treeElementForTest = root;
+                    treeOutline.appendChild(root);
+                    if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
+                        root.expand();
+
+                    this._populateStackTraceTreeElement(root);
+                    this._formattedMessage = ol;
+                }
+            }
+        }
+
+        // This is used for inline message bubbles in SourceFrames, or other plain-text representations.
+        this.message = this._formattedMessage.textContent;
+    },
+
+    isErrorOrWarning: function()
+    {
+        return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
+    },
+
+    _format: function(parameters)
+    {
+        // This node is used like a Builder. Values are continually appended onto it.
+        var formattedResult = document.createElement("span");
+        if (!parameters.length)
+            return formattedResult;
+
+        // Formatting code below assumes that parameters are all wrappers whereas frontend console
+        // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
+        for (var i = 0; i < parameters.length; ++i) {
+            if (typeof parameters[i] === "object")
+                parameters[i] = WebInspector.RemoteObject.fromPayload(parameters[i]);
+            else
+                parameters[i] = WebInspector.RemoteObject.fromPrimitiveValue(parameters[i]);
+        }
+
+        // There can be string log and string eval result. We distinguish between them based on message type.
+        var shouldFormatMessage = WebInspector.RemoteObject.type(parameters[0]) === "string" && this.type !== WebInspector.ConsoleMessage.MessageType.Result;
+
+        // Multiple parameters with the first being a format string. Save unused substitutions.
+        if (shouldFormatMessage) {
+            // Multiple parameters with the first being a format string. Save unused substitutions.
+            var result = this._formatWithSubstitutionString(parameters, formattedResult);
+            parameters = result.unusedSubstitutions;
+            if (parameters.length)
+                formattedResult.appendChild(document.createTextNode(" "));
+        }
+
+        // Single parameter, or unused substitutions from above.
+        for (var i = 0; i < parameters.length; ++i) {
+            // Inline strings when formatting.
+            if (shouldFormatMessage && parameters[i].type === "string")
+                formattedResult.appendChild(document.createTextNode(parameters[i].description));
+            else
+                formattedResult.appendChild(WebInspector.console._format(parameters[i]));
+            if (i < parameters.length - 1)
+                formattedResult.appendChild(document.createTextNode(" "));
+        }
+        return formattedResult;
+    },
+
+    _formatWithSubstitutionString: function(parameters, formattedResult)
+    {
+        var formatters = {}
+        for (var i in String.standardFormatters)
+            formatters[i] = String.standardFormatters[i];
+
+        function consoleFormatWrapper(force)
+        {
+            return function(obj) {
+                return WebInspector.console._format(obj, force);
+            };
+        }
+
+        // Firebug uses %o for formatting objects.
+        formatters.o = consoleFormatWrapper();
+        // Firebug allows both %i and %d for formatting integers.
+        formatters.i = formatters.d;
+        // Support %O to force object formatting, instead of the type-based %o formatting.
+        formatters.O = consoleFormatWrapper(true);
+
+        function append(a, b)
+        {
+            if (!(b instanceof Node))
+                a.appendChild(WebInspector.linkifyStringAsFragment(b.toString()));
+            else
+                a.appendChild(b);
+            return a;
+        }
+
+        // String.format does treat formattedResult like a Builder, result is an object.
+        return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append);
+    },
+
+    toMessageElement: function()
+    {
+        if (this._element)
+            return this._element;
+
+        var element = document.createElement("div");
+        element.message = this;
+        element.className = "console-message";
+
+        this._element = element;
+
+        switch (this.level) {
+            case WebInspector.ConsoleMessage.MessageLevel.Tip:
+                element.addStyleClass("console-tip-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Log:
+                element.addStyleClass("console-log-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Debug:
+                element.addStyleClass("console-debug-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Warning:
+                element.addStyleClass("console-warning-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Error:
+                element.addStyleClass("console-error-level");
+                break;
+        }
+
+        if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup || this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed)
+            element.addStyleClass("console-group-title");
+
+        if (this.elementsTreeOutline) {
+            element.addStyleClass("outline-disclosure");
+            element.appendChild(this.elementsTreeOutline.element);
+            return element;
+        }
+
+        element.appendChild(this._formattedMessage);
+
+        if (this.repeatCount > 1)
+            this._updateRepeatCount();
+
+        return element;
+    },
+
+    _populateStackTraceTreeElement: function(parentTreeElement)
+    {
+        for (var i = 0; i < this._stackTrace.length; i++) {
+            var frame = this._stackTrace[i];
+
+            var content = document.createElement("div");
+            var messageTextElement = document.createElement("span");
+            messageTextElement.className = "console-message-text source-code";
+            var functionName = frame.functionName || WebInspector.UIString("(anonymous function)");
+            messageTextElement.appendChild(document.createTextNode(functionName));
+            content.appendChild(messageTextElement);
+
+            var urlElement = WebInspector.linkifyResourceAsNode(frame.scriptName, "scripts", frame.lineNumber, "console-message-url");
+            content.appendChild(urlElement);
+
+            var treeElement = new TreeElement(content);
+            parentTreeElement.appendChild(treeElement);
+        }
+    },
+
+    _updateRepeatCount: function() {
+        if (!this.repeatCountElement) {
+            this.repeatCountElement = document.createElement("span");
+            this.repeatCountElement.className = "bubble";
+
+            this._element.insertBefore(this.repeatCountElement, this._element.firstChild);
+            this._element.addStyleClass("repeated-message");
+        }
+        this.repeatCountElement.textContent = this.repeatCount;
+    },
+
+    toString: function()
+    {
+        var sourceString;
+        switch (this.source) {
+            case WebInspector.ConsoleMessage.MessageSource.HTML:
+                sourceString = "HTML";
+                break;
+            case WebInspector.ConsoleMessage.MessageSource.WML:
+                sourceString = "WML";
+                break;
+            case WebInspector.ConsoleMessage.MessageSource.XML:
+                sourceString = "XML";
+                break;
+            case WebInspector.ConsoleMessage.MessageSource.JS:
+                sourceString = "JS";
+                break;
+            case WebInspector.ConsoleMessage.MessageSource.CSS:
+                sourceString = "CSS";
+                break;
+            case WebInspector.ConsoleMessage.MessageSource.Other:
+                sourceString = "Other";
+                break;
+        }
+
+        var typeString;
+        switch (this.type) {
+            case WebInspector.ConsoleMessage.MessageType.Log:
+            case WebInspector.ConsoleMessage.MessageType.UncaughtException:
+            case WebInspector.ConsoleMessage.MessageType.NetworkError:
+                typeString = "Log";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Object:
+                typeString = "Object";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Trace:
+                typeString = "Trace";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed:
+            case WebInspector.ConsoleMessage.MessageType.StartGroup:
+                typeString = "Start Group";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.EndGroup:
+                typeString = "End Group";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Assert:
+                typeString = "Assert";
+                break;
+            case WebInspector.ConsoleMessage.MessageType.Result:
+                typeString = "Result";
+                break;
+        }
+
+        var levelString;
+        switch (this.level) {
+            case WebInspector.ConsoleMessage.MessageLevel.Tip:
+                levelString = "Tip";
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Log:
+                levelString = "Log";
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Warning:
+                levelString = "Warning";
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Debug:
+                levelString = "Debug";
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Error:
+                levelString = "Error";
+                break;
+        }
+
+        return sourceString + " " + typeString + " " + levelString + ": " + this._formattedMessage.textContent + "\n" + this.url + " line " + this.line;
+    },
+
+    isEqual: function(msg)
+    {
+        if (!msg)
+            return false;
+
+        if (this._stackTrace) {
+            if (!msg._stackTrace)
+                return false;
+            var l = this._stackTrace;
+            var r = msg._stackTrace;
+            for (var i = 0; i < l.length; i++) {
+                if (l[i].scriptName !== r[i].scriptName ||
+                    l[i].functionName !== r[i].functionName ||
+                    l[i].lineNumber !== r[i].lineNumber ||
+                    l[i].column !== r[i].column)
+                    return false;
+            }
+        }
+
+        return (this.source === msg.source)
+            && (this.type === msg.type)
+            && (this.level === msg.level)
+            && (this.line === msg.line)
+            && (this.url === msg.url)
+            && (this.message === msg.message)
+            && (this._requestId === msg._requestId);
+    }
+}
+
+// Note: Keep these constants in sync with the ones in Console.h
+WebInspector.ConsoleMessage.MessageSource = {
+    HTML: 0,
+    WML: 1,
+    XML: 2,
+    JS: 3,
+    CSS: 4,
+    Other: 5
+}
+
+WebInspector.ConsoleMessage.MessageType = {
+    Log: 0,
+    Object: 1,
+    Trace: 2,
+    StartGroup: 3,
+    StartGroupCollapsed: 4,
+    EndGroup: 5,
+    Assert: 6,
+    UncaughtException: 7,
+    NetworkError:8,
+    Result: 9
+}
+
+WebInspector.ConsoleMessage.MessageLevel = {
+    Tip: 0,
+    Log: 1,
+    Warning: 2,
+    Error: 3,
+    Debug: 4
+}
+
+WebInspector.ConsoleCommand = function(command)
+{
+    this.command = command;
+}
+
+WebInspector.ConsoleCommand.prototype = {
+    toMessageElement: function()
+    {
+        var element = document.createElement("div");
+        element.command = this;
+        element.className = "console-user-command";
+
+        var commandTextElement = document.createElement("span");
+        commandTextElement.className = "console-message-text source-code";
+        commandTextElement.textContent = this.command;
+        element.appendChild(commandTextElement);
+
+        return element;
+    }
+}
+
+WebInspector.ConsoleCommandResult = function(result, originatingCommand)
+{
+    var level = (result.isError() ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
+    this.originatingCommand = originatingCommand;
+    WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Result, level, -1, null, 1, null, [result]);
+}
+
+WebInspector.ConsoleCommandResult.prototype = {
+    toMessageElement: function()
+    {
+        var element = WebInspector.ConsoleMessage.prototype.toMessageElement.call(this);
+        element.addStyleClass("console-user-command-result");
+        return element;
+    }
+}
+
+WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;
+
+WebInspector.ConsoleGroup = function(parentGroup)
+{
+    this.parentGroup = parentGroup;
+
+    var element = document.createElement("div");
+    element.className = "console-group";
+    element.group = this;
+    this.element = element;
+
+    var messagesElement = document.createElement("div");
+    messagesElement.className = "console-group-messages";
+    element.appendChild(messagesElement);
+    this.messagesElement = messagesElement;
+}
+
+WebInspector.ConsoleGroup.prototype = {
+    addMessage: function(msg)
+    {
+        var element = msg.toMessageElement();
+
+        if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) {
+            this.messagesElement.parentNode.insertBefore(element, this.messagesElement);
+            element.addEventListener("click", this._titleClicked.bind(this), false);
+            var groupElement = element.enclosingNodeOrSelfWithClass("console-group");
+            if (groupElement && msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed)
+                groupElement.addStyleClass("collapsed");
+        } else
+            this.messagesElement.appendChild(element);
+
+        if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand)
+            element.previousSibling.addStyleClass("console-adjacent-user-command-result");
+    },
+
+    _titleClicked: function(event)
+    {
+        var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title");
+        if (groupTitleElement) {
+            var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group");
+            if (groupElement)
+                if (groupElement.hasStyleClass("collapsed"))
+                    groupElement.removeStyleClass("collapsed");
+                else
+                    groupElement.addStyleClass("collapsed");
+            groupTitleElement.scrollIntoViewIfNeeded(true);
+        }
+
+        event.stopPropagation();
+        event.preventDefault();
+    }
+}
+
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ContextMenu.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ContextMenu.js
new file mode 100644
index 0000000..58810fb
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ContextMenu.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ContextMenu = function() {
+    this._items = [];
+    this._handlers = {};
+}
+
+WebInspector.ContextMenu.prototype = {
+    show: function(event)
+    {
+        // Remove trailing separator.
+        while (this._items.length > 0 && !("id" in this._items[this._items.length - 1]))
+            this._items.splice(this._items.length - 1, 1);
+
+        if (this._items.length) {
+            WebInspector._contextMenu = this;
+            InspectorFrontendHost.showContextMenu(event, this._items);
+        }
+        event.stopPropagation();
+    },
+
+    appendItem: function(label, handler, disabled)
+    {
+        var id = this._items.length;
+        this._items.push({type: "item", id: id, label: label, enabled: !disabled});
+        this._handlers[id] = handler;
+    },
+
+    appendCheckboxItem: function(label, handler, checked, disabled)
+    {
+        var id = this._items.length;
+        this._items.push({type: "checkbox", id: id, label: label, checked: !!checked, enabled: !disabled});
+        this._handlers[id] = handler;
+    },
+
+    appendSeparator: function()
+    {
+        // No separator dupes allowed.
+        if (this._items.length === 0)
+            return;
+        if (!("id" in this._items[this._items.length - 1]))
+            return;
+        this._items.push({type: "separator"});
+    },
+
+    _itemSelected: function(id)
+    {
+        if (this._handlers[id])
+            this._handlers[id].call(this);
+    }
+}
+
+WebInspector.contextMenuItemSelected = function(id)
+{
+    if (WebInspector._contextMenu)
+        WebInspector._contextMenu._itemSelected(id);
+}
+
+WebInspector.contextMenuCleared = function()
+{
+    // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected
+    // so we can't delete last menu object from WebInspector. Fix the contract.
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieItemsView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieItemsView.js
new file mode 100644
index 0000000..dc76b39
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieItemsView.js
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CookieItemsView = function(treeElement, cookieDomain)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("storage-view");
+
+    this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
+    this._deleteButton.visible = false;
+    this._deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+    this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
+    this._refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+
+    this._treeElement = treeElement;
+    this._cookieDomain = cookieDomain;
+
+    this._emptyMsgElement = document.createElement("div");
+    this._emptyMsgElement.className = "storage-empty-view";
+    this._emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies.");
+    this.element.appendChild(this._emptyMsgElement);
+}
+
+WebInspector.CookieItemsView.prototype = {
+    get statusBarItems()
+    {
+        return [this._refreshButton.element, this._deleteButton.element];
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this._update();
+    },
+
+    hide: function()
+    {
+        WebInspector.View.prototype.hide.call(this);
+        this._deleteButton.visible = false;
+    },
+
+    resize: function()
+    {
+        if (this._cookiesTable)
+            this._cookiesTable.updateWidths();
+    },
+
+    _update: function()
+    {
+        WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this));
+    },
+
+    _updateWithCookies: function(allCookies, isAdvanced)
+    {
+        this._cookies = isAdvanced ? this._filterCookiesForDomain(allCookies) : allCookies;
+
+        if (!this._cookies.length) {
+            // Nothing to show.
+            this._emptyMsgElement.removeStyleClass("hidden");
+            this._deleteButton.visible = false;
+            if (this._cookiesTable)
+                this._cookiesTable.element.addStyleClass("hidden");
+            return;
+        }
+
+        if (!this._cookiesTable) {
+            this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this)) : new WebInspector.SimpleCookiesTable();
+            this.element.appendChild(this._cookiesTable.element);
+        }
+
+        this._cookiesTable.setCookies(this._cookies);
+        this._cookiesTable.element.removeStyleClass("hidden");
+        this._emptyMsgElement.addStyleClass("hidden");
+        if (isAdvanced) {
+            this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length,
+                Number.bytesToString(this._totalSize));
+            this._deleteButton.visible = true;
+        }
+        this._cookiesTable.updateWidths();
+    },
+
+    _filterCookiesForDomain: function(allCookies)
+    {
+        var cookies = [];
+        var resourceURLsForDocumentURL = [];
+        this._totalSize = 0;
+
+        function populateResourcesForDocuments(resource)
+        {
+            var url = resource.documentURL.asParsedURL();
+            if (url && url.host == this._cookieDomain)
+                resourceURLsForDocumentURL.push(resource.url);
+        }
+        WebInspector.forAllResources(populateResourcesForDocuments.bind(this));
+
+        for (var i = 0; i < allCookies.length; ++i) {
+            var pushed = false;
+            var size = allCookies[i].size;
+            for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) {
+                var resourceURL = resourceURLsForDocumentURL[j];
+                if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) {
+                    this._totalSize += size;
+                    if (!pushed) {
+                        pushed = true;
+                        cookies.push(allCookies[i]);
+                    }
+                }
+            }
+        }
+        return cookies;
+    },
+
+    _deleteCookie: function(cookie)
+    {
+        InspectorBackend.deleteCookie(cookie.name, this._cookieDomain);
+        this._update();
+    },
+
+    _deleteButtonClicked: function()
+    {
+        if (this._cookiesTable.selectedCookie)
+            this._deleteCookie(this._cookiesTable.selectedCookie);
+    },
+
+    _refreshButtonClicked: function(event)
+    {
+        this._update();
+    }
+}
+
+WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.SimpleCookiesTable = function()
+{
+    this.element = document.createElement("div");
+    var columns = {};
+    columns[0] = {};
+    columns[1] = {};
+    columns[0].title = WebInspector.UIString("Name");
+    columns[1].title = WebInspector.UIString("Value");
+
+    this._dataGrid = new WebInspector.DataGrid(columns);
+    this._dataGrid.autoSizeColumns(20, 80);
+    this.element.appendChild(this._dataGrid.element);
+    this._dataGrid.updateWidths();
+}
+
+WebInspector.SimpleCookiesTable.prototype = {
+    setCookies: function(cookies)
+    {
+        this._dataGrid.removeChildren();
+        var addedCookies = {};
+        for (var i = 0; i < cookies.length; ++i) {
+            if (addedCookies[cookies[i].name])
+                continue;
+            addedCookies[cookies[i].name] = true;
+            var data = {};
+            data[0] = cookies[i].name;
+            data[1] = cookies[i].value;
+
+            var node = new WebInspector.DataGridNode(data, false);
+            node.selectable = true;
+            this._dataGrid.appendChild(node);
+        }
+        this._dataGrid.children[0].selected = true;
+    },
+
+    resize: function()
+    {
+        if (this._dataGrid)
+            this._dataGrid.updateWidths();
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieParser.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieParser.js
new file mode 100755
index 0000000..f96be0b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookieParser.js
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Ideally, we would rely on platform support for parsing a cookie, since
+// this would save us from any potential inconsistency. However, exposing
+// platform cookie parsing logic would require quite a bit of additional 
+// plumbing, and at least some platforms lack support for parsing Cookie,
+// which is in a format slightly different from Set-Cookie and is normally 
+// only required on the server side.
+
+WebInspector.CookieParser = function()
+{
+}
+
+WebInspector.CookieParser.prototype = {
+    get cookies()
+    {
+        return this._cookies;
+    },
+
+    parseCookie: function(cookieHeader)
+    {
+        if (!this._initialize(cookieHeader))
+            return;
+
+        for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
+            if (kv.key.charAt(0) === "$" && this._lastCookie)
+                this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
+            else if (kv.key.toLowerCase() !== "$version" && typeof kv.value === "string")
+                this._addCookie(kv, WebInspector.Cookie.Type.Request);
+            this._advanceAndCheckCookieDelimiter();
+        }
+        this._flushCookie();
+        return this._cookies;
+    },
+
+    parseSetCookie: function(setCookieHeader)
+    {
+        if (!this._initialize(setCookieHeader))
+            return;
+        for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
+            if (this._lastCookie)
+                this._lastCookie.addAttribute(kv.key, kv.value);
+            else 
+                this._addCookie(kv, WebInspector.Cookie.Type.Response);
+            if (this._advanceAndCheckCookieDelimiter())
+                this._flushCookie();
+        }
+        this._flushCookie();
+        return this._cookies;
+    },
+
+    _initialize: function(headerValue)
+    {
+        this._input = headerValue;
+        if (typeof headerValue !== "string")
+            return false;
+        this._cookies = [];
+        this._lastCookie = null;
+        this._originalInputLength = this._input.length;
+        return true;
+    },
+
+    _flushCookie: function()
+    {
+        if (this._lastCookie)
+            this._lastCookie.size = this._originalInputLength - this._input.length - this._lastCookiePosition;
+        this._lastCookie = null;
+    },
+
+    _extractKeyValue: function()
+    {
+        if (!this._input || !this._input.length)
+            return null;
+        // Note: RFCs offer an option for quoted values that may contain commas and semicolons.
+        // Many browsers/platforms do not support this, however (see http://webkit.org/b/16699
+        // and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox,
+        // Chrome and Safari on some old platforms. The latest version of Safari supports quoted
+        // cookie values, though. 
+        var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input);
+        if (!keyValueMatch) {
+            console.log("Failed parsing cookie header before: " + this._input);
+            return null;
+        }
+
+        var result = {
+            key: keyValueMatch[1],
+            value: keyValueMatch[2] && keyValueMatch[2].trim(),
+            position: this._originalInputLength - this._input.length
+        };
+        this._input = this._input.slice(keyValueMatch[0].length);
+        return result;
+    },
+
+    _advanceAndCheckCookieDelimiter: function()
+    {
+        var match = /^\s*[\n;]\s*/.exec(this._input);
+        if (!match)
+            return false;
+        this._input = this._input.slice(match[0].length);
+        return match[0].match("\n") !== null;
+    },
+
+    _addCookie: function(keyValue, type)
+    {
+        if (this._lastCookie)
+            this._lastCookie.size = keyValue.position - this._lastCookiePosition;
+        // Mozilla bug 169091: Mozilla, IE and Chrome treat single token (w/o "=") as
+        // specifying a value for a cookie with empty name.
+        this._lastCookie = keyValue.value ? new WebInspector.Cookie(keyValue.key, keyValue.value, type) :
+            new WebInspector.Cookie("", keyValue.key, type);
+        this._lastCookiePosition = keyValue.position;
+        this._cookies.push(this._lastCookie);
+    }
+};
+
+WebInspector.CookieParser.parseCookie = function(header)
+{
+    return (new WebInspector.CookieParser()).parseCookie(header);
+}
+
+WebInspector.CookieParser.parseSetCookie = function(header)
+{
+    return (new WebInspector.CookieParser()).parseSetCookie(header);
+}
+
+WebInspector.Cookie = function(name, value, type)
+{
+    this.name = name;
+    this.value = value;
+    this.type = type;
+    this._attributes = {};
+}
+
+WebInspector.Cookie.prototype = {
+    get httpOnly()
+    {
+        return "httponly" in this._attributes;
+    },
+
+    get secure()
+    {
+        return "secure" in this._attributes;
+    },
+
+    get session()
+    {
+        // RFC 2965 suggests using Discard attribute to mark session cookies, but this does not seem to be widely used.
+        // Check for absence of explicity max-age or expiry date instead.
+        return  !("expries" in this._attributes || "max-age" in this._attributes);
+    },
+
+    get path()
+    {
+        return this._attributes.path;
+    },
+
+    get domain()
+    {
+        return this._attributes.domain;
+    },
+
+    expires: function(requestDate)
+    {
+        return this._attributes.expires ? new Date(this._attributes.expires) :
+            (this._attributes["max-age"] ? new Date(requestDate.getTime() + 1000 * this._attributes["max-age"]) : null);
+    },
+
+    get attributes()
+    {
+        return this._attributes;
+    },
+
+    addAttribute: function(key, value)
+    {
+        this._attributes[key.toLowerCase()] = value;
+    }
+}
+
+WebInspector.Cookie.Type = {
+    Request: 0,
+    Response: 1
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookiesTable.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookiesTable.js
new file mode 100644
index 0000000..2382a8e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/CookiesTable.js
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CookiesTable = function(cookieDomain, expandable, deleteCallback)
+{
+    this._cookieDomain = cookieDomain;
+
+    var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} };
+    columns[0].title = WebInspector.UIString("Name");
+    columns[0].sortable = true;
+    columns[0].disclosure = expandable;
+    columns[0].width = "24%";
+    columns[1].title = WebInspector.UIString("Value");
+    columns[1].sortable = true;
+    columns[1].width = "34%";
+    columns[2].title = WebInspector.UIString("Domain");
+    columns[2].sortable = true;
+    columns[2].width = "7%";
+    columns[3].title = WebInspector.UIString("Path");
+    columns[3].sortable = true;
+    columns[3].width = "7%";
+    columns[4].title = WebInspector.UIString("Expires");
+    columns[4].sortable = true;
+    columns[4].width = "7%";
+    columns[5].title = WebInspector.UIString("Size");
+    columns[5].aligned = "right";
+    columns[5].sortable = true;
+    columns[5].width = "7%";
+    columns[6].title = WebInspector.UIString("HTTP");
+    columns[6].aligned = "centered";
+    columns[6].sortable = true;
+    columns[6].width = "7%";
+    columns[7].title = WebInspector.UIString("Secure");
+    columns[7].aligned = "centered";
+    columns[7].sortable = true;
+    columns[7].width = "7%";
+
+    this._dataGrid = new WebInspector.DataGrid(columns, null, deleteCallback ? this._onDeleteFromGrid.bind(this) : null);
+    this._dataGrid.addEventListener("sorting changed", this._rebuildTable, this);
+
+    this.element = this._dataGrid.element;
+    this._data = [];
+    this._deleteCallback = deleteCallback;
+}
+
+WebInspector.CookiesTable.prototype = {
+    updateWidths: function()
+    {
+        if (this._dataGrid)
+            this._dataGrid.updateWidths();
+    },
+
+    setCookies: function(cookies)
+    {
+        this._data = [{cookies: cookies}];
+        this._rebuildTable();
+    },
+
+    addCookiesFolder: function(folderName, cookies)
+    {
+        this._data.push({cookies: cookies, folderName: folderName});
+        this._rebuildTable();
+    },
+
+    get selectedCookie()
+    {
+        var node = this._dataGrid.selectedNode;
+        return node ? node.cookie : null;
+    },
+
+    _rebuildTable: function()
+    {
+        this._dataGrid.removeChildren();
+        for (var i = 0; i < this._data.length; ++i) {
+            var item = this._data[i];
+            if (item.folderName) {
+                var groupData = [ item.folderName, "", "", "", "", this._totalSize(item.cookies), "", "" ];
+                var groupNode = new WebInspector.DataGridNode(groupData);
+                groupNode.selectable = true;
+                this._dataGrid.appendChild(groupNode);
+                groupNode.element.addStyleClass("row-group");
+                this._populateNode(groupNode, item.cookies);
+                groupNode.expand();
+            } else
+                this._populateNode(this._dataGrid, item.cookies);
+        }
+    },
+
+    _populateNode: function(parentNode, cookies)
+    {
+        var selectedCookie = this.selectedCookie;
+        parentNode.removeChildren();
+        if (!cookies)
+            return;
+
+        this._sortCookies(cookies);
+        for (var i = 0; i < cookies.length; ++i) {
+            var cookieNode = this._createGridNode(cookies[i]);
+            parentNode.appendChild(cookieNode);
+            if (selectedCookie === cookies[i])
+                cookieNode.selected = true;
+        }
+    },
+
+    _totalSize: function(cookies)
+    {
+        var totalSize = 0;
+        for (var i = 0; cookies && i < cookies.length; ++i)
+            totalSize += cookies[i].size;
+        return totalSize;
+    },
+
+    _sortCookies: function(cookies)
+    {
+        var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;
+
+        function localeCompare(field, cookie1, cookie2)
+        {
+            return sortDirection * (cookie1[field] + "").localeCompare(cookie2[field] + "")
+        }
+
+        function numberCompare(field, cookie1, cookie2)
+        {
+            return sortDirection * (cookie1[field] - cookie2[field]);
+        }
+
+        function expiresCompare(cookie1, cookie2)
+        {
+            if (cookie1.session !== cookie2.session)
+                return sortDirection * (cookie1.session ? 1 : -1);
+
+            if (cookie1.session)
+                return 0;
+
+            return sortDirection * (cookie1.expires - cookie2.expires);
+        }
+
+        var comparator;
+        switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
+            case 0: comparator = localeCompare.bind(this, "name"); break;
+            case 1: comparator = localeCompare.bind(this, "value"); break;
+            case 2: comparator = localeCompare.bind(this, "domain"); break;
+            case 3: comparator = localeCompare.bind(this, "path"); break;
+            case 4: comparator = expiresCompare; break;
+            case 5: comparator = numberCompare.bind(this, "size"); break;
+            case 6: comparator = localeCompare.bind(this, "httpOnly"); break;
+            case 7: comparator = localeCompare.bind(this, "secure"); break;
+            default: localeCompare.bind(this, "name");
+        }
+
+        cookies.sort(comparator);
+    },
+
+    _createGridNode: function(cookie)
+    {
+        var data = {};
+        data[0] = cookie.name;
+        data[1] = cookie.value;
+        data[2] = cookie.domain || "";
+        data[3] = cookie.path || "";
+        data[4] = cookie.type === WebInspector.Cookie.Type.Request ? "" :
+            (cookie.session ? WebInspector.UIString("Session") : new Date(cookie.expires).toGMTString());
+        data[5] = cookie.size;
+        const checkmark = "\u2713";
+        data[6] = (cookie.httpOnly ? checkmark : "");
+        data[7] = (cookie.secure ? checkmark : "");
+
+        var node = new WebInspector.DataGridNode(data);
+        node.cookie = cookie;
+        node.selectable = true;
+        return node;
+    },
+
+    _onDeleteFromGrid: function(node)
+    {
+        this._deleteCallback(node.cookie);
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMAgent.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMAgent.js
new file mode 100644
index 0000000..3645bb9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMAgent.js
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DOMNode = function(doc, payload) {
+    this.ownerDocument = doc;
+
+    this.id = payload.id;
+    this.nodeType = payload.nodeType;
+    this.nodeName = payload.nodeName;
+    this.localName = payload.localName;
+    this._nodeValue = payload.nodeValue;
+    this.textContent = this.nodeValue;
+
+    this.attributes = [];
+    this._attributesMap = {};
+    if (payload.attributes)
+        this._setAttributesPayload(payload.attributes);
+
+    this._childNodeCount = payload.childNodeCount;
+    this.children = null;
+
+    this.nextSibling = null;
+    this.prevSibling = null;
+    this.firstChild = null;
+    this.lastChild = null;
+    this.parentNode = null;
+
+    if (payload.children)
+        this._setChildrenPayload(payload.children);
+
+    this._computedStyle = null;
+    this.style = null;
+    this._matchedCSSRules = [];
+
+    this.breakpoints = {};
+
+    if (this.nodeType === Node.ELEMENT_NODE) {
+        // HTML and BODY from internal iframes should not overwrite top-level ones.
+        if (!this.ownerDocument.documentElement && this.nodeName === "HTML")
+            this.ownerDocument.documentElement = this;
+        if (!this.ownerDocument.body && this.nodeName === "BODY")
+            this.ownerDocument.body = this;
+        if (payload.documentURL)
+            this.documentURL = payload.documentURL;
+    } else if (this.nodeType === Node.DOCUMENT_TYPE_NODE) {
+        this.publicId = payload.publicId;
+        this.systemId = payload.systemId;
+        this.internalSubset = payload.internalSubset;
+    } else if (this.nodeType === Node.DOCUMENT_NODE) {
+        this.documentURL = payload.documentURL;
+    } else if (this.nodeType === Node.ATTRIBUTE_NODE) {
+        this.name = payload.name;
+        this.value = payload.value;
+    }
+}
+
+WebInspector.DOMNode.prototype = {
+    hasAttributes: function()
+    {
+        return this.attributes.length > 0;
+    },
+
+    hasChildNodes: function()
+    {
+        return this._childNodeCount > 0;
+    },
+
+    get nodeValue() {
+        return this._nodeValue;
+    },
+
+    set nodeValue(value) {
+        if (this.nodeType != Node.TEXT_NODE)
+            return;
+        this.ownerDocument._domAgent.setTextNodeValueAsync(this, value, function() {});
+    },
+
+    getAttribute: function(name)
+    {
+        var attr = this._attributesMap[name];
+        return attr ? attr.value : undefined;
+    },
+
+    setAttribute: function(name, value)
+    {
+        var self = this;
+        var callback = function()
+        {
+            var attr = self._attributesMap[name];
+            if (attr)
+                attr.value = value;
+            else
+                attr = self._addAttribute(name, value);
+        };
+        this.ownerDocument._domAgent.setAttributeAsync(this, name, value, callback);
+    },
+
+    removeAttribute: function(name)
+    {
+        var self = this;
+        var callback = function()
+        {
+            delete self._attributesMap[name];
+            for (var i = 0;  i < self.attributes.length; ++i) {
+                if (self.attributes[i].name == name) {
+                    self.attributes.splice(i, 1);
+                    break;
+                }
+            }
+        };
+        this.ownerDocument._domAgent.removeAttributeAsync(this, name, callback);
+    },
+
+    path: function()
+    {
+        var path = [];
+        var node = this;
+        while (node && "index" in node && node.nodeName.length) {
+            path.push([node.index, node.nodeName]);
+            node = node.parentNode;
+        }
+        path.reverse();
+        return path.join(",");
+    },
+
+    _setAttributesPayload: function(attrs)
+    {
+        this.attributes = [];
+        this._attributesMap = {};
+        for (var i = 0; i < attrs.length; i += 2)
+            this._addAttribute(attrs[i], attrs[i + 1]);
+    },
+
+    _insertChild: function(prev, payload)
+    {
+        var node = new WebInspector.DOMNode(this.ownerDocument, payload);
+        if (!prev) {
+            if (!this.children) {
+                // First node
+                this.children = [ node ];
+            } else
+                this.children.unshift(node);
+        } else
+            this.children.splice(this.children.indexOf(prev) + 1, 0, node);
+        this._renumber();
+        return node;
+    },
+
+    removeChild_: function(node)
+    {
+        this.children.splice(this.children.indexOf(node), 1);
+        node.parentNode = null;
+        this._renumber();
+    },
+
+    _setChildrenPayload: function(payloads)
+    {
+        this.children = [];
+        for (var i = 0; i < payloads.length; ++i) {
+            var payload = payloads[i];
+            var node = new WebInspector.DOMNode(this.ownerDocument, payload);
+            this.children.push(node);
+        }
+        this._renumber();
+    },
+
+    _renumber: function()
+    {
+        this._childNodeCount = this.children.length;
+        if (this._childNodeCount == 0) {
+            this.firstChild = null;
+            this.lastChild = null;
+            return;
+        }
+        this.firstChild = this.children[0];
+        this.lastChild = this.children[this._childNodeCount - 1];
+        for (var i = 0; i < this._childNodeCount; ++i) {
+            var child = this.children[i];
+            child.index = i;
+            child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null;
+            child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null;
+            child.parentNode = this;
+        }
+    },
+
+    _addAttribute: function(name, value)
+    {
+        var attr = {
+            "name": name,
+            "value": value,
+            "_node": this
+        };
+        this._attributesMap[name] = attr;
+        this.attributes.push(attr);
+    }
+}
+
+WebInspector.DOMDocument = function(domAgent, defaultView, payload)
+{
+    WebInspector.DOMNode.call(this, this, payload);
+    this._listeners = {};
+    this._domAgent = domAgent;
+    this.defaultView = defaultView;
+}
+
+WebInspector.DOMDocument.prototype = {
+
+    addEventListener: function(name, callback)
+    {
+        var listeners = this._listeners[name];
+        if (!listeners) {
+            listeners = [];
+            this._listeners[name] = listeners;
+        }
+        listeners.push(callback);
+    },
+
+    removeEventListener: function(name, callback)
+    {
+        var listeners = this._listeners[name];
+        if (!listeners)
+            return;
+
+        var index = listeners.indexOf(callback);
+        if (index != -1)
+            listeners.splice(index, 1);
+    },
+
+    _fireDomEvent: function(name, event)
+    {
+        var listeners = this._listeners[name];
+        if (!listeners)
+            return;
+
+        for (var i = 0; i < listeners.length; ++i) {
+            var listener = listeners[i];
+            listener.call(this, event);
+        }
+    }
+}
+
+WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;
+
+
+WebInspector.DOMWindow = function(domAgent)
+{
+    this._domAgent = domAgent;
+}
+
+WebInspector.DOMWindow.prototype = {
+    get document()
+    {
+        return this._domAgent.document;
+    },
+
+    get Node()
+    {
+        return WebInspector.DOMNode;
+    },
+
+    get Element()
+    {
+        return WebInspector.DOMNode;
+    },
+
+    Object: function()
+    {
+    }
+}
+
+WebInspector.DOMAgent = function() {
+    this._window = new WebInspector.DOMWindow(this);
+    this._idToDOMNode = null;
+    this.document = null;
+    InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
+}
+
+WebInspector.DOMAgent.prototype = {
+    get domWindow()
+    {
+        return this._window;
+    },
+
+    getChildNodesAsync: function(parent, callback)
+    {
+        var children = parent.children;
+        if (children) {
+            callback(children);
+            return;
+        }
+        function mycallback() {
+            callback(parent.children);
+        }
+        InspectorBackend.getChildNodes(parent.id, mycallback);
+    },
+
+    setAttributeAsync: function(node, name, value, callback)
+    {
+        var mycallback = this._didApplyDomChange.bind(this, node, callback);
+        InspectorBackend.setAttribute(node.id, name, value, mycallback);
+    },
+
+    removeAttributeAsync: function(node, name, callback)
+    {
+        var mycallback = this._didApplyDomChange.bind(this, node, callback);
+        InspectorBackend.removeAttribute(node.id, name, mycallback);
+    },
+
+    setTextNodeValueAsync: function(node, text, callback)
+    {
+        var mycallback = this._didApplyDomChange.bind(this, node, callback);
+        InspectorBackend.setTextNodeValue(node.id, text, mycallback);
+    },
+
+    _didApplyDomChange: function(node, callback, success)
+    {
+        if (!success)
+            return;
+        callback();
+        // TODO(pfeldman): Fix this hack.
+        var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node);
+        if (elem)
+            elem.updateTitle();
+    },
+
+    _attributesUpdated: function(nodeId, attrsArray)
+    {
+        var node = this._idToDOMNode[nodeId];
+        node._setAttributesPayload(attrsArray);
+        var event = {target: node};
+        this.document._fireDomEvent("DOMAttrModified", event);
+    },
+
+    _characterDataModified: function(nodeId, newValue)
+    {
+        var node = this._idToDOMNode[nodeId];
+        node._nodeValue = newValue;
+        node.textContent = newValue;
+        var event = { target : node };
+        this.document._fireDomEvent("DOMCharacterDataModified", event);
+    },
+
+    nodeForId: function(nodeId)
+    {
+        return this._idToDOMNode[nodeId];
+    },
+
+    _setDocument: function(payload)
+    {
+        this._idToDOMNode = {};
+        if (payload && "id" in payload) {
+            this.document = new WebInspector.DOMDocument(this, this._window, payload);
+            this._idToDOMNode[payload.id] = this.document;
+            this._bindNodes(this.document.children);
+            WebInspector.breakpointManager.restoreDOMBreakpoints();
+        } else
+            this.document = null;
+        WebInspector.panels.elements.setDocument(this.document);
+    },
+
+    _setDetachedRoot: function(payload)
+    {
+        var root = new WebInspector.DOMNode(this.document, payload);
+        this._idToDOMNode[payload.id] = root;
+    },
+
+    _setChildNodes: function(parentId, payloads)
+    {
+        var parent = this._idToDOMNode[parentId];
+        parent._setChildrenPayload(payloads);
+        this._bindNodes(parent.children);
+    },
+
+    _bindNodes: function(children)
+    {
+        for (var i = 0; i < children.length; ++i) {
+            var child = children[i];
+            this._idToDOMNode[child.id] = child;
+            if (child.children)
+                this._bindNodes(child.children);
+        }
+    },
+
+    _childNodeCountUpdated: function(nodeId, newValue)
+    {
+        var node = this._idToDOMNode[nodeId];
+        node._childNodeCount = newValue;
+        var outline = WebInspector.panels.elements.treeOutline;
+        var treeElement = outline.findTreeElement(node);
+        if (treeElement)
+            treeElement.hasChildren = newValue;
+    },
+
+    _childNodeInserted: function(parentId, prevId, payload)
+    {
+        var parent = this._idToDOMNode[parentId];
+        var prev = this._idToDOMNode[prevId];
+        var node = parent._insertChild(prev, payload);
+        this._idToDOMNode[node.id] = node;
+        var event = { target : node, relatedNode : parent };
+        this.document._fireDomEvent("DOMNodeInserted", event);
+    },
+
+    _childNodeRemoved: function(parentId, nodeId)
+    {
+        var parent = this._idToDOMNode[parentId];
+        var node = this._idToDOMNode[nodeId];
+        parent.removeChild_(node);
+        var event = { target : node, relatedNode : parent };
+        this.document._fireDomEvent("DOMNodeRemoved", event);
+        delete this._idToDOMNode[nodeId];
+        this._removeBreakpoints(node);
+    },
+
+    _removeBreakpoints: function(node)
+    {
+        for (var type in node.breakpoints)
+            node.breakpoints[type].remove();
+        if (!node.children)
+            return;
+        for (var i = 0; i < node.children.length; ++i)
+            this._removeBreakpoints(node.children[i]);
+    }
+}
+
+WebInspector.DOMDispatcher = function(domAgent)
+{
+    this._domAgent = domAgent;
+}
+
+WebInspector.DOMDispatcher.prototype = {
+    setDocument: function(payload)
+    {
+        this._domAgent._setDocument(payload);
+    },
+
+    attributesUpdated: function(nodeId, attrsArray)
+    {
+        this._domAgent._attributesUpdated(nodeId, attrsArray);
+    },
+
+    characterDataModified: function(nodeId, newValue)
+    {
+        this._domAgent._characterDataModified(nodeId, newValue);
+    },
+
+    setChildNodes: function(parentId, payloads)
+    {
+        this._domAgent._setChildNodes(parentId, payloads);
+    },
+
+    setDetachedRoot: function(payload)
+    {
+        this._domAgent._setDetachedRoot(payload);
+    },
+
+    childNodeCountUpdated: function(nodeId, newValue)
+    {
+        this._domAgent._childNodeCountUpdated(nodeId, newValue);
+    },
+
+    childNodeInserted: function(parentId, prevId, payload)
+    {
+        this._domAgent._childNodeInserted(parentId, prevId, payload);
+    },
+
+    childNodeRemoved: function(parentId, nodeId)
+    {
+        this._domAgent._childNodeRemoved(parentId, nodeId);
+    }
+}
+
+WebInspector.ApplicationCacheDispatcher = function()
+{
+}
+
+WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync = function(callback)
+{
+    function mycallback(applicationCaches)
+    {
+        // FIXME: Currently, this list only returns a single application cache.
+        if (applicationCaches)
+            callback(applicationCaches);
+    }
+
+    InspectorBackend.getApplicationCaches(mycallback);
+}
+
+WebInspector.ApplicationCacheDispatcher.prototype = {
+    updateApplicationCacheStatus: function(status)
+    {
+        WebInspector.panels.resources.updateApplicationCacheStatus(status);
+    },
+
+    updateNetworkState: function(isNowOnline)
+    {
+        WebInspector.panels.resources.updateNetworkState(isNowOnline);
+    }
+}
+
+InspectorBackend.registerDomainDispatcher("ApplicationCache", new WebInspector.ApplicationCacheDispatcher());
+
+WebInspector.Cookies = {}
+
+WebInspector.Cookies.getCookiesAsync = function(callback)
+{
+    function mycallback(cookies, cookiesString)
+    {
+        if (cookiesString)
+            callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false);
+        else
+            callback(cookies, true);
+    }
+
+    InspectorBackend.getCookies(mycallback);
+}
+
+WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
+{
+    var rawCookies = rawCookieString.split(/;\s*/);
+    var cookies = [];
+
+    if (!(/^\s*$/.test(rawCookieString))) {
+        for (var i = 0; i < rawCookies.length; ++i) {
+            var cookie = rawCookies[i];
+            var delimIndex = cookie.indexOf("=");
+            var name = cookie.substring(0, delimIndex);
+            var value = cookie.substring(delimIndex + 1);
+            var size = name.length + value.length;
+            cookies.push({ name: name, value: value, size: size });
+        }
+    }
+
+    return cookies;
+}
+
+WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
+{
+    var url = resourceURL.asParsedURL();
+    if (!url || !this.cookieDomainMatchesResourceDomain(cookie.domain, url.host))
+        return false;
+    return (url.path.indexOf(cookie.path) === 0
+        && (!cookie.port || url.port == cookie.port)
+        && (!cookie.secure || url.scheme === "https"));
+}
+
+WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
+{
+    if (cookieDomain.charAt(0) !== '.')
+        return resourceDomain === cookieDomain;
+    return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i");
+}
+
+WebInspector.EventListeners = {}
+
+WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callback)
+{
+    if (!node)
+        return;
+    InspectorBackend.getEventListenersForNode(node.id, callback);
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorage.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorage.js
new file mode 100644
index 0000000..43011ea
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorage.js
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Nokia Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DOMStorage = function(id, domain, isLocalStorage)
+{
+    this._id = id;
+    this._domain = domain;
+    this._isLocalStorage = isLocalStorage;
+}
+
+WebInspector.DOMStorage.prototype = {
+    get id()
+    {
+        return this._id;
+    },
+
+    get domain()
+    {
+        return this._domain;
+    },
+
+    get isLocalStorage()
+    {
+        return this._isLocalStorage;
+    },
+
+    getEntries: function(callback)
+    {
+        InspectorBackend.getDOMStorageEntries(this._id, callback);
+    },
+    
+    setItem: function(key, value, callback)
+    {
+        InspectorBackend.setDOMStorageItem(this._id, key, value, callback);
+    },
+    
+    removeItem: function(key, callback)
+    {
+        InspectorBackend.removeDOMStorageItem(this._id, key, callback);
+    }
+}
+
+
+WebInspector.DOMStorageDispatcher = function()
+{
+}
+
+WebInspector.DOMStorageDispatcher.prototype = {
+    addDOMStorage: function(payload)
+    {
+        if (!WebInspector.panels.resources)
+            return;
+        var domStorage = new WebInspector.DOMStorage(
+            payload.id,
+            payload.host,
+            payload.isLocalStorage);
+        WebInspector.panels.resources.addDOMStorage(domStorage);
+    },
+
+    selectDOMStorage: function(o)
+    {
+        WebInspector.showPanel("resources");
+        WebInspector.panels.resources.selectDOMStorage(o);
+    },
+
+    updateDOMStorage: function(storageId)
+    {
+        WebInspector.panels.resources.updateDOMStorage(storageId);
+    }
+}
+
+InspectorBackend.registerDomainDispatcher("DOMStorage", new WebInspector.DOMStorageDispatcher());
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorageItemsView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorageItemsView.js
new file mode 100644
index 0000000..dbd736b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMStorageItemsView.js
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2008 Nokia Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DOMStorageItemsView = function(domStorage)
+{
+    WebInspector.View.call(this);
+
+    this.domStorage = domStorage;
+
+    this.element.addStyleClass("storage-view");
+    this.element.addStyleClass("table");
+
+    this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
+    this.deleteButton.visible = false;
+    this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+    this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
+    this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+}
+
+WebInspector.DOMStorageItemsView.prototype = {
+    get statusBarItems()
+    {
+        return [this.refreshButton.element, this.deleteButton.element];
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this.update();
+    },
+
+    hide: function()
+    {
+        WebInspector.View.prototype.hide.call(this);
+        this.deleteButton.visible = false;
+    },
+
+    update: function()
+    {
+        this.element.removeChildren();
+        var callback = this._showDOMStorageEntries.bind(this);
+        this.domStorage.getEntries(callback);
+    },
+
+    _showDOMStorageEntries: function(entries)
+    {
+        this._dataGrid = this._dataGridForDOMStorageEntries(entries);
+        this.element.appendChild(this._dataGrid.element);
+        this._dataGrid.autoSizeColumns(10);
+        this.deleteButton.visible = true;
+    },
+
+    resize: function()
+    {
+        if (this._dataGrid)
+            this._dataGrid.updateWidths();
+    },
+
+    _dataGridForDOMStorageEntries: function(entries)
+    {
+        var columns = {};
+        columns[0] = {};
+        columns[1] = {};
+        columns[0].title = WebInspector.UIString("Key");
+        columns[1].title = WebInspector.UIString("Value");
+
+        var nodes = [];
+
+        var keys = [];
+        var length = entries.length;
+        for (var i = 0; i < entries.length; i++) {
+            var data = {};
+
+            var key = entries[i][0];
+            data[0] = key;
+            var value = entries[i][1];
+            data[1] = value;
+            var node = new WebInspector.DataGridNode(data, false);
+            node.selectable = true;
+            nodes.push(node);
+            keys.push(key);
+        }
+
+        var dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this));
+        var length = nodes.length;
+        for (var i = 0; i < length; ++i)
+            dataGrid.appendChild(nodes[i]);
+        dataGrid.addCreationNode(false);
+        if (length > 0)
+            nodes[0].selected = true;
+        return dataGrid;
+    },
+
+    _deleteButtonClicked: function(event)
+    {
+        if (!this._dataGrid || !this._dataGrid.selectedNode)
+            return;
+
+        this._deleteCallback(this._dataGrid.selectedNode);
+    },
+
+    _refreshButtonClicked: function(event)
+    {
+        this.update();
+    },
+    
+    _editingCallback: function(editingNode, columnIdentifier, oldText, newText)
+    {
+        var domStorage = this.domStorage;
+        if (columnIdentifier === 0) {
+            if (oldText)
+                domStorage.removeItem(oldText);
+
+            domStorage.setItem(newText, editingNode.data[1]);
+        } else {
+            domStorage.setItem(editingNode.data[0], newText);
+        }
+        
+        this.update();
+    },
+    
+    _deleteCallback: function(node)
+    {
+        if (!node || node.isCreationNode)
+            return;
+
+        if (this.domStorage)
+            this.domStorage.removeItem(node.data[0]);
+            
+        this.update();
+    }
+}
+
+WebInspector.DOMStorageItemsView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMSyntaxHighlighter.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMSyntaxHighlighter.js
new file mode 100644
index 0000000..07233d3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DOMSyntaxHighlighter.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DOMSyntaxHighlighter = function(mimeType)
+{
+    this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
+}
+
+WebInspector.DOMSyntaxHighlighter.prototype = {
+    createSpan: function(content, className)
+    {
+        var span = document.createElement("span");
+        span.className = "webkit-" + className;
+        span.appendChild(document.createTextNode(content));
+        return span;
+    },
+
+    syntaxHighlightNode: function(node)
+    {
+        this._tokenizer.condition = this._tokenizer.initialCondition;
+        var lines = node.textContent.split("\n");
+        node.removeChildren();
+
+        for (var i = lines[0].length ? 0 : 1; i < lines.length; ++i) {
+            var line = lines[i];
+            var plainTextStart = 0;
+            this._tokenizer.line = line;
+            var column = 0;
+            do {
+                var newColumn = this._tokenizer.nextToken(column);
+                var tokenType = this._tokenizer.tokenType;
+                if (tokenType) {
+                    if (column > plainTextStart) {
+                        var plainText = line.substring(plainTextStart, column);
+                        node.appendChild(document.createTextNode(plainText));
+                    }
+                    var token = line.substring(column, newColumn);
+                    node.appendChild(this.createSpan(token, tokenType));
+                    plainTextStart = newColumn;
+                }
+                column = newColumn;
+           } while (column < line.length)
+
+           if (plainTextStart < line.length) {
+               var plainText = line.substring(plainTextStart, line.length);
+               node.appendChild(document.createTextNode(plainText));
+           }
+           if (i < lines.length - 1)
+               node.appendChild(document.createElement("br"));
+        }
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DataGrid.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DataGrid.js
new file mode 100644
index 0000000..45f0b55
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DataGrid.js
@@ -0,0 +1,1478 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.         IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
+{
+    this.element = document.createElement("div");
+    this.element.className = "data-grid";
+    this.element.tabIndex = 0;
+    this.element.addEventListener("keydown", this._keyDown.bind(this), false);
+
+    this._headerTable = document.createElement("table");
+    this._headerTable.className = "header";
+    this._headerTableHeaders = {};
+
+    this._dataTable = document.createElement("table");
+    this._dataTable.className = "data";
+
+    this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
+    this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);
+    
+    this._dataTable.addEventListener("contextmenu", this._contextMenuInDataTable.bind(this), true);
+    
+    // FIXME: Add a createCallback which is different from editCallback and has different
+    // behavior when creating a new node.
+    if (editCallback) {
+        this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false);
+        this._editCallback = editCallback;
+    }
+    if (deleteCallback)
+        this._deleteCallback = deleteCallback;
+    
+    this.aligned = {};
+
+    this._scrollContainer = document.createElement("div");
+    this._scrollContainer.className = "data-container";
+    this._scrollContainer.appendChild(this._dataTable);
+
+    this.element.appendChild(this._headerTable);
+    this.element.appendChild(this._scrollContainer);
+
+    var headerRow = document.createElement("tr");
+    var columnGroup = document.createElement("colgroup");
+    this._columnCount = 0;
+
+    for (var columnIdentifier in columns) {
+        var column = columns[columnIdentifier];
+        if (column.disclosure)
+            this.disclosureColumnIdentifier = columnIdentifier;
+
+        var col = document.createElement("col");
+        if (column.width)
+            col.style.width = column.width;
+        column.element = col;
+        columnGroup.appendChild(col);
+
+        var cell = document.createElement("th");
+        cell.className = columnIdentifier + "-column";
+        cell.columnIdentifier = columnIdentifier;
+        this._headerTableHeaders[columnIdentifier] = cell;
+
+        var div = document.createElement("div");
+        if (column.titleDOMFragment)
+            div.appendChild(column.titleDOMFragment);
+        else
+            div.textContent = column.title;
+        cell.appendChild(div);
+
+        if (column.sort) {
+            cell.addStyleClass("sort-" + column.sort);
+            this._sortColumnCell = cell;
+        }
+
+        if (column.sortable) {
+            cell.addEventListener("click", this._clickInHeaderCell.bind(this), false);
+            cell.addStyleClass("sortable");
+        }
+
+        if (column.aligned)
+            this.aligned[columnIdentifier] = column.aligned;
+
+        headerRow.appendChild(cell);
+
+        ++this._columnCount;
+    }
+
+    columnGroup.span = this._columnCount;
+
+    var cell = document.createElement("th");
+    cell.className = "corner";
+    headerRow.appendChild(cell);
+
+    this._headerTableColumnGroup = columnGroup;
+    this._headerTable.appendChild(this._headerTableColumnGroup);
+    this.headerTableBody.appendChild(headerRow);
+
+    var fillerRow = document.createElement("tr");
+    fillerRow.className = "filler";
+
+    for (var columnIdentifier in columns) {
+        var column = columns[columnIdentifier];
+        var cell = document.createElement("td");
+        cell.className = columnIdentifier + "-column";
+        fillerRow.appendChild(cell);
+    }
+
+    this._dataTableColumnGroup = columnGroup.cloneNode(true);
+    this._dataTable.appendChild(this._dataTableColumnGroup);
+    this.dataTableBody.appendChild(fillerRow);
+
+    this.columns = columns || {};
+    this._columnsArray = [];
+    for (var columnIdentifier in columns) {
+        columns[columnIdentifier].ordinal = this._columnsArray.length;
+        this._columnsArray.push(columns[columnIdentifier]);
+    }
+
+    for (var i = 0; i < this._columnsArray.length; ++i)
+        this._columnsArray[i].bodyElement = this._dataTableColumnGroup.children[i];
+
+    this.children = [];
+    this.selectedNode = null;
+    this.expandNodesWhenArrowing = false;
+    this.root = true;
+    this.hasChildren = false;
+    this.expanded = true;
+    this.revealed = true;
+    this.selected = false;
+    this.dataGrid = this;
+    this.indentWidth = 15;
+    this.resizers = [];
+    this._columnWidthsInitialized = false;
+}
+
+WebInspector.DataGrid.prototype = {
+    _ondblclick: function(event)
+    {
+        if (this._editing || this._editingNode)
+            return;
+
+        this._startEditing(event.target);
+    },
+
+    _startEditingColumnOfDataGridNode: function(node, column)
+    {
+        this._editing = true;
+        this._editingNode = node;
+        this._editingNode.select();
+
+        var element = this._editingNode._element.children[column];
+        WebInspector.startEditing(element, {
+            context: element.textContent,
+            commitHandler: this._editingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(element, 0, element, 1);
+    },
+
+    _startEditing: function(target)
+    {
+        var element = target.enclosingNodeOrSelfWithNodeName("td");
+        if (!element)
+            return;
+
+        this._editingNode = this.dataGridNodeFromNode(target);
+        if (!this._editingNode) {
+            if (!this.creationNode)
+                return;
+            this._editingNode = this.creationNode;
+        }
+
+        // Force editing the 1st column when editing the creation node
+        if (this._editingNode.isCreationNode)
+            return this._startEditingColumnOfDataGridNode(this._editingNode, 0);
+
+        this._editing = true;
+        WebInspector.startEditing(element, {
+            context: element.textContent,
+            commitHandler: this._editingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(element, 0, element, 1);
+    },
+
+    _editingCommitted: function(element, newText, oldText, context, moveDirection)
+    {
+        // FIXME: We need more column identifiers here throughout this function.
+        // Not needed yet since only editable DataGrid is DOM Storage, which is Key - Value.
+        
+        // FIXME: Better way to do this than regular expressions?
+        var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1]);
+
+        var textBeforeEditing = this._editingNode.data[columnIdentifier];
+        var currentEditingNode = this._editingNode;
+
+        function moveToNextIfNeeded(wasChange) {
+            if (!moveDirection)
+                return;
+
+            if (moveDirection === "forward") {
+                if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange)
+                    return;
+
+                if (columnIdentifier === 0)
+                    return this._startEditingColumnOfDataGridNode(currentEditingNode, 1);
+
+                var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true);
+                if (nextDataGridNode)
+                    return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0);
+                if (currentEditingNode.isCreationNode && wasChange) {
+                    addCreationNode(false);
+                    return this._startEditingColumnOfDataGridNode(this.creationNode, 0);
+                }
+                return;
+            }
+
+            if (moveDirection === "backward") {
+                if (columnIdentifier === 1)
+                    return this._startEditingColumnOfDataGridNode(currentEditingNode, 0);
+                    var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true);
+
+                if (nextDataGridNode)
+                    return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1);
+                return;
+            }
+        }
+
+        if (textBeforeEditing == newText) {
+            this._editingCancelled(element);
+            moveToNextIfNeeded.call(this, false);
+            return;
+        }
+
+        // Update the text in the datagrid that we typed
+        this._editingNode.data[columnIdentifier] = newText;
+        
+        // Make the callback - expects an editing node (table row), the column number that is being edited,
+        // the text that used to be there, and the new text.
+        this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText);
+
+        if (this._editingNode.isCreationNode)
+            this.addCreationNode(false);
+
+        this._editingCancelled(element);
+        moveToNextIfNeeded.call(this, true);
+    },
+
+    _editingCancelled: function(element, context)
+    {
+        delete this._editing;
+        this._editingNode = null;
+    },
+    
+    get sortColumnIdentifier()
+    {
+        if (!this._sortColumnCell)
+            return null;
+        return this._sortColumnCell.columnIdentifier;
+    },
+
+    get sortOrder()
+    {
+        if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending"))
+            return "ascending";
+        if (this._sortColumnCell.hasStyleClass("sort-descending"))
+            return "descending";
+        return null;
+    },
+
+    get headerTableBody()
+    {
+        if ("_headerTableBody" in this)
+            return this._headerTableBody;
+
+        this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0];
+        if (!this._headerTableBody) {
+            this._headerTableBody = this.element.ownerDocument.createElement("tbody");
+            this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot);
+        }
+
+        return this._headerTableBody;
+    },
+
+    get dataTableBody()
+    {
+        if ("_dataTableBody" in this)
+            return this._dataTableBody;
+
+        this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0];
+        if (!this._dataTableBody) {
+            this._dataTableBody = this.element.ownerDocument.createElement("tbody");
+            this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot);
+        }
+
+        return this._dataTableBody;
+    },
+
+    autoSizeColumns: function(minPercent, maxPercent, maxDescentLevel)
+    {
+        if (minPercent)
+            minPercent = Math.min(minPercent, Math.floor(100 / this._columnCount));
+        var widths = {};
+        var columns = this.columns;
+        for (var columnIdentifier in columns)
+            widths[columnIdentifier] = (columns[columnIdentifier].title || "").length;
+
+        var children = maxDescentLevel ? this._enumerateChildren(this, [], maxDescentLevel + 1) : this.children;
+        for (var i = 0; i < children.length; ++i) {
+            var node = children[i];
+            for (var columnIdentifier in columns) {
+                var text = node.data[columnIdentifier] || "";
+                if (text.length > widths[columnIdentifier])
+                    widths[columnIdentifier] = text.length;
+            }
+        }
+
+        var totalColumnWidths = 0;
+        for (var columnIdentifier in columns)
+            totalColumnWidths += widths[columnIdentifier];
+
+        var recoupPercent = 0;
+        for (var columnIdentifier in columns) {
+            var width = Math.round(100 * widths[columnIdentifier] / totalColumnWidths);
+            if (minPercent && width < minPercent) {
+                recoupPercent += (minPercent - width);
+                width = minPercent;
+            } else if (maxPercent && width > maxPercent) {
+                recoupPercent -= (width - maxPercent);
+                width = maxPercent;
+            }
+            widths[columnIdentifier] = width;
+        }
+
+        while (minPercent && recoupPercent > 0) {
+            for (var columnIdentifier in columns) {
+                if (widths[columnIdentifier] > minPercent) {
+                    --widths[columnIdentifier];
+                    --recoupPercent;
+                    if (!recoupPercent)
+                        break;
+                }
+            }
+        }
+
+        while (maxPercent && recoupPercent < 0) {
+            for (var columnIdentifier in columns) {
+                if (widths[columnIdentifier] < maxPercent) {
+                    ++widths[columnIdentifier];
+                    ++recoupPercent;
+                    if (!recoupPercent)
+                        break;
+                }
+            }
+        }
+
+        for (var columnIdentifier in columns)
+            columns[columnIdentifier].element.style.width = widths[columnIdentifier] + "%";
+        this._columnWidthsInitialized = false;
+        this.updateWidths();
+    },
+
+    _enumerateChildren: function(rootNode, result, maxLevel)
+    {
+        if (!rootNode.root)
+            result.push(rootNode);
+        if (!maxLevel)
+            return;
+        for (var i = 0; i < rootNode.children.length; ++i)
+            this._enumerateChildren(rootNode.children[i], result, maxLevel - 1);
+        return result;
+    },
+
+    // Updates the widths of the table, including the positions of the column
+    // resizers.
+    //
+    // IMPORTANT: This function MUST be called once after the element of the
+    // DataGrid is attached to its parent element and every subsequent time the
+    // width of the parent element is changed in order to make it possible to
+    // resize the columns.
+    //
+    // If this function is not called after the DataGrid is attached to its
+    // parent element, then the DataGrid's columns will not be resizable.
+    updateWidths: function()
+    {
+        var headerTableColumns = this._headerTableColumnGroup.children;
+        
+        var tableWidth = this._dataTable.offsetWidth;
+        var numColumns = headerTableColumns.length;
+        
+        // Do not attempt to use offsetes if we're not attached to the document tree yet.
+        if (!this._columnWidthsInitialized && this.element.offsetWidth) {
+            // Give all the columns initial widths now so that during a resize,
+            // when the two columns that get resized get a percent value for
+            // their widths, all the other columns already have percent values
+            // for their widths.
+            for (var i = 0; i < numColumns; i++) {
+                var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth;
+                var percentWidth = ((columnWidth / tableWidth) * 100) + "%";
+                this._headerTableColumnGroup.children[i].style.width = percentWidth;
+                this._dataTableColumnGroup.children[i].style.width = percentWidth;
+            }
+            this._columnWidthsInitialized = true;
+        }
+        this._positionResizers();
+        this.dispatchEventToListeners("width changed");
+    },
+
+    columnWidthsMap: function()
+    {
+        var result = {};
+        for (var i = 0; i < this._columnsArray.length; ++i) {
+            var width = this._headerTableColumnGroup.children[i].style.width;
+            result[this._columnsArray[i].columnIdentifier] = parseFloat(width);
+        }
+        return result;
+    },
+
+    applyColumnWidthsMap: function(columnWidthsMap)
+    {
+        for (var columnIdentifier in this.columns) {
+            var column = this.columns[columnIdentifier];
+            var width = (columnWidthsMap[columnIdentifier] || 0) + "%";
+            this._headerTableColumnGroup.children[column.ordinal].style.width = width;
+            this._dataTableColumnGroup.children[column.ordinal].style.width = width;
+        }
+
+        // Normalize widths
+        delete this._columnWidthsInitialized;
+        this.updateWidths();
+    },
+
+    isColumnVisible: function(columnIdentifier)
+    {
+        var column = this.columns[columnIdentifier];
+        var columnElement = column.element;
+        return !columnElement.hidden;
+    },
+
+    showColumn: function(columnIdentifier)
+    {
+        var column = this.columns[columnIdentifier];
+        var columnElement = column.element;
+        if (!columnElement.hidden)
+            return;
+
+        columnElement.hidden = false;
+        columnElement.removeStyleClass("hidden");
+
+        var columnBodyElement = column.bodyElement;
+        columnBodyElement.hidden = false;
+        columnBodyElement.removeStyleClass("hidden");
+    },
+
+    hideColumn: function(columnIdentifier)
+    {
+        var column = this.columns[columnIdentifier];
+        var columnElement = column.element;
+        if (columnElement.hidden)
+            return;
+
+        var oldWidth = parseFloat(columnElement.style.width);
+
+        columnElement.hidden = true;
+        columnElement.addStyleClass("hidden");
+        columnElement.style.width = 0;
+
+        var columnBodyElement = column.bodyElement;
+        columnBodyElement.hidden = true;
+        columnBodyElement.addStyleClass("hidden");
+        columnBodyElement.style.width = 0;
+
+        this._columnWidthsInitialized = false;
+    },
+
+    get scrollContainer()
+    {
+        return this._scrollContainer;        
+    },
+
+    isScrolledToLastRow: function()
+    {
+        return this._scrollContainer.isScrolledToBottom();
+    },
+
+    scrollToLastRow: function()
+    {
+        this._scrollContainer.scrollTop = this._scrollContainer.scrollHeight - this._scrollContainer.offsetHeight;
+    },
+
+    _positionResizers: function()
+    {
+        var headerTableColumns = this._headerTableColumnGroup.children;
+        var numColumns = headerTableColumns.length;
+        var left = 0;
+        var previousResizer = null;
+
+        // Make n - 1 resizers for n columns. 
+        for (var i = 0; i < numColumns - 1; i++) {
+            var resizer = this.resizers[i];
+
+            if (!resizer) {
+                // This is the first call to updateWidth, so the resizers need
+                // to be created.
+                resizer = document.createElement("div");
+                resizer.addStyleClass("data-grid-resizer");
+                // This resizer is associated with the column to its right.
+                resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
+                this.element.appendChild(resizer);
+                this.resizers[i] = resizer;
+            }
+
+            // Get the width of the cell in the first (and only) row of the
+            // header table in order to determine the width of the column, since
+            // it is not possible to query a column for its width.
+            left += this.headerTableBody.rows[0].cells[i].offsetWidth;
+
+            var columnIsVisible = !this._headerTableColumnGroup.children[i].hidden;
+            if (columnIsVisible) {
+                resizer.style.removeProperty("display");
+                resizer.style.left = left + "px";
+                resizer.leftNeighboringColumnID = i;
+                if (previousResizer)
+                    previousResizer.rightNeighboringColumnID = i;
+                previousResizer = resizer;
+            } else {
+                resizer.style.setProperty("display", "none");
+                resizer.leftNeighboringColumnID = 0;
+                resizer.rightNeighboringColumnID = 0;
+            }
+        }
+        if (previousResizer)
+            previousResizer.rightNeighboringColumnID = numColumns - 1;
+    },
+
+    addCreationNode: function(hasChildren)
+    {
+        if (this.creationNode)
+            this.creationNode.makeNormal();
+
+        var emptyData = {};
+        for (var column in this.columns)
+            emptyData[column] = '';
+        this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren);
+        this.appendChild(this.creationNode);
+    },
+
+    appendChild: function(child)
+    {
+        this.insertChild(child, this.children.length);
+    },
+
+    insertChild: function(child, index)
+    {
+        if (!child)
+            throw("insertChild: Node can't be undefined or null.");
+        if (child.parent === this)
+            throw("insertChild: Node is already a child of this node.");
+
+        if (child.parent)
+            child.parent.removeChild(child);
+
+        this.children.splice(index, 0, child);
+        this.hasChildren = true;
+
+        child.parent = this;
+        child.dataGrid = this.dataGrid;
+        child._recalculateSiblings(index);
+
+        delete child._depth;
+        delete child._revealed;
+        delete child._attached;
+        child._shouldRefreshChildren = true;
+
+        var current = child.children[0];
+        while (current) {
+            current.dataGrid = this.dataGrid;
+            delete current._depth;
+            delete current._revealed;
+            delete current._attached;
+            current._shouldRefreshChildren = true;
+            current = current.traverseNextNode(false, child, true);
+        }
+
+        if (this.expanded)
+            child._attach();
+    },
+
+    removeChild: function(child)
+    {
+        if (!child)
+            throw("removeChild: Node can't be undefined or null.");
+        if (child.parent !== this)
+            throw("removeChild: Node is not a child of this node.");
+
+        child.deselect();
+        child._detach();
+
+        this.children.remove(child, true);
+
+        if (child.previousSibling)
+            child.previousSibling.nextSibling = child.nextSibling;
+        if (child.nextSibling)
+            child.nextSibling.previousSibling = child.previousSibling;
+
+        child.dataGrid = null;
+        child.parent = null;
+        child.nextSibling = null;
+        child.previousSibling = null;
+
+        if (this.children.length <= 0)
+            this.hasChildren = false;
+    },
+
+    removeChildren: function()
+    {
+        for (var i = 0; i < this.children.length; ++i) {
+            var child = this.children[i];
+            child.deselect();
+            child._detach();
+
+            child.dataGrid = null;
+            child.parent = null;
+            child.nextSibling = null;
+            child.previousSibling = null;
+        }
+
+        this.children = [];
+        this.hasChildren = false;
+    },
+
+    removeChildrenRecursive: function()
+    {
+        var childrenToRemove = this.children;
+
+        var child = this.children[0];
+        while (child) {
+            if (child.children.length)
+                childrenToRemove = childrenToRemove.concat(child.children);
+            child = child.traverseNextNode(false, this, true);
+        }
+
+        for (var i = 0; i < childrenToRemove.length; ++i) {
+            var child = childrenToRemove[i];
+            child.deselect();
+            child._detach();
+
+            child.children = [];
+            child.dataGrid = null;
+            child.parent = null;
+            child.nextSibling = null;
+            child.previousSibling = null;
+        }
+
+        this.children = [];
+    },
+
+    sortNodes: function(comparator, reverseMode)
+    {
+        function comparatorWrapper(a, b)
+        {
+            if (a._dataGridNode._data.summaryRow)
+                return 1;
+            if (b._dataGridNode._data.summaryRow)
+                return -1;
+
+            var aDataGirdNode = a._dataGridNode;
+            var bDataGirdNode = b._dataGridNode;
+            return reverseMode ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode);
+        }
+
+        var tbody = this.dataTableBody;
+        var tbodyParent = tbody.parentElement;
+        tbodyParent.removeChild(tbody);
+
+        var childNodes = tbody.childNodes;
+        var fillerRow = childNodes[childNodes.length - 1];
+
+        var sortedRows = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1);
+        sortedRows.sort(comparatorWrapper);
+        var sortedRowsLength = sortedRows.length;
+
+        tbody.removeChildren();
+        var previousSiblingNode = null;
+        for (var i = 0; i < sortedRowsLength; ++i) {
+            var row = sortedRows[i];
+            var node = row._dataGridNode;
+            node.previousSibling = previousSiblingNode;
+            if (previousSiblingNode)
+                previousSiblingNode.nextSibling = node;
+            tbody.appendChild(row);
+            previousSiblingNode = node;
+        }
+        if (previousSiblingNode)
+            previousSiblingNode.nextSibling = null;
+
+        tbody.appendChild(fillerRow);
+        tbodyParent.appendChild(tbody);
+    },
+
+    _keyDown: function(event)
+    {
+        if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing)
+            return;
+
+        var handled = false;
+        var nextSelectedNode;
+        if (event.keyIdentifier === "Up" && !event.altKey) {
+            nextSelectedNode = this.selectedNode.traversePreviousNode(true);
+            while (nextSelectedNode && !nextSelectedNode.selectable)
+                nextSelectedNode = nextSelectedNode.traversePreviousNode(!this.expandTreeNodesWhenArrowing);
+            handled = nextSelectedNode ? true : false;
+        } else if (event.keyIdentifier === "Down" && !event.altKey) {
+            nextSelectedNode = this.selectedNode.traverseNextNode(true);
+            while (nextSelectedNode && !nextSelectedNode.selectable)
+                nextSelectedNode = nextSelectedNode.traverseNextNode(!this.expandTreeNodesWhenArrowing);
+            handled = nextSelectedNode ? true : false;
+        } else if (event.keyIdentifier === "Left") {
+            if (this.selectedNode.expanded) {
+                if (event.altKey)
+                    this.selectedNode.collapseRecursively();
+                else
+                    this.selectedNode.collapse();
+                handled = true;
+            } else if (this.selectedNode.parent && !this.selectedNode.parent.root) {
+                handled = true;
+                if (this.selectedNode.parent.selectable) {
+                    nextSelectedNode = this.selectedNode.parent;
+                    handled = nextSelectedNode ? true : false;
+                } else if (this.selectedNode.parent)
+                    this.selectedNode.parent.collapse();
+            }
+        } else if (event.keyIdentifier === "Right") {
+            if (!this.selectedNode.revealed) {
+                this.selectedNode.reveal();
+                handled = true;
+            } else if (this.selectedNode.hasChildren) {
+                handled = true;
+                if (this.selectedNode.expanded) {
+                    nextSelectedNode = this.selectedNode.children[0];
+                    handled = nextSelectedNode ? true : false;
+                } else {
+                    if (event.altKey)
+                        this.selectedNode.expandRecursively();
+                    else
+                        this.selectedNode.expand();
+                }
+            }
+        } else if (event.keyCode === 8 || event.keyCode === 46) {
+            if (this._deleteCallback) {
+                handled = true;
+                this._deleteCallback(this.selectedNode);
+            }
+        } else if (isEnterKey(event)) {
+            if (this._editCallback) {
+                handled = true;
+                // The first child of the selected element is the <td class="0-column">,
+                // and that's what we want to edit.
+                this._startEditing(this.selectedNode._element.children[0]);
+            }
+        }
+
+        if (nextSelectedNode) {
+            nextSelectedNode.reveal();
+            nextSelectedNode.select();
+        }
+
+        if (handled) {
+            event.preventDefault();
+            event.stopPropagation();
+        }
+    },
+
+    expand: function()
+    {
+        // This is the root, do nothing.
+    },
+
+    collapse: function()
+    {
+        // This is the root, do nothing.
+    },
+
+    reveal: function()
+    {
+        // This is the root, do nothing.
+    },
+
+    dataGridNodeFromNode: function(target)
+    {
+        var rowElement = target.enclosingNodeOrSelfWithNodeName("tr");
+        return rowElement._dataGridNode;
+    },
+
+    dataGridNodeFromPoint: function(x, y)
+    {
+        var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
+        var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
+        return rowElement._dataGridNode;
+    },
+
+    _clickInHeaderCell: function(event)
+    {
+        var cell = event.target.enclosingNodeOrSelfWithNodeName("th");
+        if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable"))
+            return;
+
+        var sortOrder = this.sortOrder;
+
+        if (this._sortColumnCell)
+            this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");
+
+        if (cell == this._sortColumnCell) {
+            if (sortOrder === "ascending")
+                sortOrder = "descending";
+            else
+                sortOrder = "ascending";
+        }
+
+        this._sortColumnCell = cell;
+
+        cell.addStyleClass("sort-" + sortOrder);
+
+        this.dispatchEventToListeners("sorting changed");
+    },
+
+    markColumnAsSortedBy: function(columnIdentifier, sortOrder)
+    {
+        if (this._sortColumnCell)
+            this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");
+        this._sortColumnCell = this._headerTableHeaders[columnIdentifier];
+        this._sortColumnCell.addStyleClass("sort-" + sortOrder);
+    },
+
+    headerTableHeader: function(columnIdentifier)
+    {
+        return this._headerTableHeaders[columnIdentifier];
+    },
+
+    _mouseDownInDataTable: function(event)
+    {
+        var gridNode = this.dataGridNodeFromNode(event.target);
+        if (!gridNode || !gridNode.selectable)
+            return;
+
+        if (gridNode.isEventWithinDisclosureTriangle(event))
+            return;
+
+        if (event.metaKey) {
+            if (gridNode.selected)
+                gridNode.deselect();
+            else
+                gridNode.select();
+        } else
+            gridNode.select();
+    },
+    
+    _contextMenuInDataTable: function(event)
+    {
+        var gridNode = this.dataGridNodeFromNode(event.target);
+        if (!gridNode || !gridNode.selectable)
+            return;
+        
+        if (gridNode.isEventWithinDisclosureTriangle(event))
+            return;
+      
+        var contextMenu = new WebInspector.ContextMenu();
+        
+        // FIXME: Use the column names for Editing, instead of just "Edit".
+        if (this.dataGrid._editCallback) {
+            if (gridNode === this.creationNode)
+                contextMenu.appendItem(WebInspector.UIString("Add New"), this._startEditing.bind(this, event.target));
+            else
+                contextMenu.appendItem(WebInspector.UIString("Edit"), this._startEditing.bind(this, event.target));
+        }
+        if (this.dataGrid._deleteCallback && gridNode !== this.creationNode)
+            contextMenu.appendItem(WebInspector.UIString("Delete"), this._deleteCallback.bind(this, gridNode));
+        
+        contextMenu.show(event);
+    },
+
+    _clickInDataTable: function(event)
+    {
+        var gridNode = this.dataGridNodeFromNode(event.target);
+        if (!gridNode || !gridNode.hasChildren)
+            return;
+
+        if (!gridNode.isEventWithinDisclosureTriangle(event))
+            return;
+
+        if (gridNode.expanded) {
+            if (event.altKey)
+                gridNode.collapseRecursively();
+            else
+                gridNode.collapse();
+        } else {
+            if (event.altKey)
+                gridNode.expandRecursively();
+            else
+                gridNode.expand();
+        }
+    },
+    
+    _startResizerDragging: function(event)
+    {
+        this.currentResizer = event.target;
+        if (!this.currentResizer.rightNeighboringColumnID)
+            return;
+        WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bind(this),
+            this._endResizerDragging.bind(this), event, "col-resize");
+    },
+    
+    _resizerDragging: function(event)
+    {
+        var resizer = this.currentResizer;
+        if (!resizer)
+            return;
+        
+        // Constrain the dragpoint to be within the containing div of the
+        // datagrid.
+        var dragPoint = event.clientX - this.element.totalOffsetLeft;
+        // Constrain the dragpoint to be within the space made up by the
+        // column directly to the left and the column directly to the right.
+        var leftEdgeOfPreviousColumn = 0;
+        var firstRowCells = this.headerTableBody.rows[0].cells;
+        for (var i = 0; i < resizer.leftNeighboringColumnID; i++)
+            leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
+            
+        var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.leftNeighboringColumnID].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth;
+
+        // Give each column some padding so that they don't disappear.
+        var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding;
+        var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding;
+
+        dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
+
+        resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
+
+        var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%";
+        this._headerTableColumnGroup.children[resizer.leftNeighboringColumnID].style.width = percentLeftColumn;
+        this._dataTableColumnGroup.children[resizer.leftNeighboringColumnID].style.width = percentLeftColumn;
+
+        var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%";
+        this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width =  percentRightColumn;
+        this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
+
+        this._positionResizers();
+        event.preventDefault();
+        this.dispatchEventToListeners("width changed");
+    },
+    
+    _endResizerDragging: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+        this.currentResizer = null;
+        this.dispatchEventToListeners("width changed");
+    },
+    
+    ColumnResizePadding: 10,
+    
+    CenterResizerOverBorderAdjustment: 3,
+}
+
+WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DataGridNode = function(data, hasChildren)
+{
+    this._expanded = false;
+    this._selected = false;
+    this._shouldRefreshChildren = true;
+    this._data = data || {};
+    this.hasChildren = hasChildren || false;
+    this.children = [];
+    this.dataGrid = null;
+    this.parent = null;
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this.disclosureToggleWidth = 10;
+}
+
+WebInspector.DataGridNode.prototype = {
+    selectable: true,
+
+    get element()
+    {
+        if (this._element)
+            return this._element;
+
+        if (!this.dataGrid)
+            return null;
+
+        this._element = document.createElement("tr");
+        this._element._dataGridNode = this;
+
+        if (this.hasChildren)
+            this._element.addStyleClass("parent");
+        if (this.expanded)
+            this._element.addStyleClass("expanded");
+        if (this.selected)
+            this._element.addStyleClass("selected");
+        if (this.revealed)
+            this._element.addStyleClass("revealed");
+
+        this.createCells();
+        return this._element;
+    },
+
+    createCells: function()
+    {
+        for (var columnIdentifier in this.dataGrid.columns) {
+            var cell = this.createCell(columnIdentifier);
+            this._element.appendChild(cell);
+        }
+    },
+
+    get data()
+    {
+        return this._data;
+    },
+
+    set data(x)
+    {
+        this._data = x || {};
+        this.refresh();
+    },
+
+    get revealed()
+    {
+        if ("_revealed" in this)
+            return this._revealed;
+
+        var currentAncestor = this.parent;
+        while (currentAncestor && !currentAncestor.root) {
+            if (!currentAncestor.expanded) {
+                this._revealed = false;
+                return false;
+            }
+
+            currentAncestor = currentAncestor.parent;
+        }
+
+        this._revealed = true;
+        return true;
+    },
+
+    set hasChildren(x)
+    {
+        if (this._hasChildren === x)
+            return;
+
+        this._hasChildren = x;
+
+        if (!this._element)
+            return;
+
+        if (this._hasChildren)
+        {
+            this._element.addStyleClass("parent");
+            if (this.expanded)
+                this._element.addStyleClass("expanded");
+        }
+        else
+        {
+            this._element.removeStyleClass("parent");
+            this._element.removeStyleClass("expanded");
+        }
+    },
+
+    get hasChildren()
+    {
+        return this._hasChildren;
+    },
+
+    set revealed(x)
+    {
+        if (this._revealed === x)
+            return;
+
+        this._revealed = x;
+
+        if (this._element) {
+            if (this._revealed)
+                this._element.addStyleClass("revealed");
+            else
+                this._element.removeStyleClass("revealed");
+        }
+
+        for (var i = 0; i < this.children.length; ++i)
+            this.children[i].revealed = x && this.expanded;
+    },
+
+    get depth()
+    {
+        if ("_depth" in this)
+            return this._depth;
+        if (this.parent && !this.parent.root)
+            this._depth = this.parent.depth + 1;
+        else
+            this._depth = 0;
+        return this._depth;
+    },
+
+    get shouldRefreshChildren()
+    {
+        return this._shouldRefreshChildren;
+    },
+
+    set shouldRefreshChildren(x)
+    {
+        this._shouldRefreshChildren = x;
+        if (x && this.expanded)
+            this.expand();
+    },
+
+    get selected()
+    {
+        return this._selected;
+    },
+
+    set selected(x)
+    {
+        if (x)
+            this.select();
+        else
+            this.deselect();
+    },
+
+    get expanded()
+    {
+        return this._expanded;
+    },
+
+    set expanded(x)
+    {
+        if (x)
+            this.expand();
+        else
+            this.collapse();
+    },
+
+    refresh: function()
+    {
+        if (!this._element || !this.dataGrid)
+            return;
+
+        this._element.removeChildren();
+        this.createCells();
+    },
+
+    createCell: function(columnIdentifier)
+    {
+        var cell = document.createElement("td");
+        cell.className = columnIdentifier + "-column";
+
+        var alignment = this.dataGrid.aligned[columnIdentifier];
+        if (alignment)
+            cell.addStyleClass(alignment);
+
+        var div = document.createElement("div");
+        div.textContent = this.data[columnIdentifier];
+        cell.appendChild(div);
+
+        if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
+            cell.addStyleClass("disclosure");
+            if (this.depth)
+                cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+        }
+
+        return cell;
+    },
+
+    // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
+    appendChild: WebInspector.DataGrid.prototype.appendChild,
+    insertChild: WebInspector.DataGrid.prototype.insertChild,
+    removeChild: WebInspector.DataGrid.prototype.removeChild,
+    removeChildren: WebInspector.DataGrid.prototype.removeChildren,
+    removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,
+
+    _recalculateSiblings: function(myIndex)
+    {
+        if (!this.parent)
+            return;
+
+        var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
+
+        if (previousChild) {
+            previousChild.nextSibling = this;
+            this.previousSibling = previousChild;
+        } else
+            this.previousSibling = null;
+
+        var nextChild = this.parent.children[myIndex + 1];
+
+        if (nextChild) {
+            nextChild.previousSibling = this;
+            this.nextSibling = nextChild;
+        } else
+            this.nextSibling = null;
+    },
+
+    collapse: function()
+    {
+        if (this._element)
+            this._element.removeStyleClass("expanded");
+
+        this._expanded = false;
+
+        for (var i = 0; i < this.children.length; ++i)
+            this.children[i].revealed = false;
+
+        this.dispatchEventToListeners("collapsed");
+    },
+
+    collapseRecursively: function()
+    {
+        var item = this;
+        while (item) {
+            if (item.expanded)
+                item.collapse();
+            item = item.traverseNextNode(false, this, true);
+        }
+    },
+
+    expand: function()
+    {
+        if (!this.hasChildren || this.expanded)
+            return;
+
+        if (this.revealed && !this._shouldRefreshChildren)
+            for (var i = 0; i < this.children.length; ++i)
+                this.children[i].revealed = true;
+
+        if (this._shouldRefreshChildren) {
+            for (var i = 0; i < this.children.length; ++i)
+                this.children[i]._detach();
+
+            this.dispatchEventToListeners("populate");
+
+            if (this._attached) {
+                for (var i = 0; i < this.children.length; ++i) {
+                    var child = this.children[i];
+                    if (this.revealed)
+                        child.revealed = true;
+                    child._attach();
+                }
+            }
+
+            delete this._shouldRefreshChildren;
+        }
+
+        if (this._element)
+            this._element.addStyleClass("expanded");
+
+        this._expanded = true;
+
+        this.dispatchEventToListeners("expanded");
+    },
+
+    expandRecursively: function()
+    {
+        var item = this;
+        while (item) {
+            item.expand();
+            item = item.traverseNextNode(false, this);
+        }
+    },
+
+    reveal: function()
+    {
+        var currentAncestor = this.parent;
+        while (currentAncestor && !currentAncestor.root) {
+            if (!currentAncestor.expanded)
+                currentAncestor.expand();
+            currentAncestor = currentAncestor.parent;
+        }
+
+        this.element.scrollIntoViewIfNeeded(false);
+
+        this.dispatchEventToListeners("revealed");
+    },
+
+    select: function(supressSelectedEvent)
+    {
+        if (!this.dataGrid || !this.selectable || this.selected)
+            return;
+
+        if (this.dataGrid.selectedNode)
+            this.dataGrid.selectedNode.deselect();
+
+        this._selected = true;
+        this.dataGrid.selectedNode = this;
+
+        if (this._element)
+            this._element.addStyleClass("selected");
+
+        if (!supressSelectedEvent)
+            this.dispatchEventToListeners("selected");
+    },
+
+    deselect: function(supressDeselectedEvent)
+    {
+        if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+            return;
+
+        this._selected = false;
+        this.dataGrid.selectedNode = null;
+
+        if (this._element)
+            this._element.removeStyleClass("selected");
+
+        if (!supressDeselectedEvent)
+            this.dispatchEventToListeners("deselected");
+    },
+
+    traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info)
+    {
+        if (!dontPopulate && this.hasChildren)
+            this.dispatchEventToListeners("populate");
+
+        if (info)
+            info.depthChange = 0;
+
+        var node = (!skipHidden || this.revealed) ? this.children[0] : null;
+        if (node && (!skipHidden || this.expanded)) {
+            if (info)
+                info.depthChange = 1;
+            return node;
+        }
+
+        if (this === stayWithin)
+            return null;
+
+        node = (!skipHidden || this.revealed) ? this.nextSibling : null;
+        if (node)
+            return node;
+
+        node = this;
+        while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
+            if (info)
+                info.depthChange -= 1;
+            node = node.parent;
+        }
+
+        if (!node)
+            return null;
+
+        return (!skipHidden || node.revealed) ? node.nextSibling : null;
+    },
+
+    traversePreviousNode: function(skipHidden, dontPopulate)
+    {
+        var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
+        if (!dontPopulate && node && node.hasChildren)
+            node.dispatchEventToListeners("populate");
+
+        while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
+            if (!dontPopulate && node.hasChildren)
+                node.dispatchEventToListeners("populate");
+            node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
+        }
+
+        if (node)
+            return node;
+
+        if (!this.parent || this.parent.root)
+            return null;
+
+        return this.parent;
+    },
+
+    isEventWithinDisclosureTriangle: function(event)
+    {
+        if (!this.hasChildren)
+            return false;
+        var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+        if (!cell.hasStyleClass("disclosure"))
+            return false;
+        var computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
+        var left = cell.totalOffsetLeft + computedLeftPadding;
+        return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
+    },
+
+    _attach: function()
+    {
+        if (!this.dataGrid || this._attached)
+            return;
+
+        this._attached = true;
+
+        var nextNode = null;
+        var previousNode = this.traversePreviousNode(true, true);
+        if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling)
+            var nextNode = previousNode.element.nextSibling;
+        if (!nextNode)
+            nextNode = this.dataGrid.dataTableBody.lastChild;
+        this.dataGrid.dataTableBody.insertBefore(this.element, nextNode);
+
+        if (this.expanded)
+            for (var i = 0; i < this.children.length; ++i)
+                this.children[i]._attach();
+    },
+
+    _detach: function()
+    {
+        if (!this._attached)
+            return;
+
+        this._attached = false;
+
+        if (this._element && this._element.parentNode)
+            this._element.parentNode.removeChild(this._element);
+
+        for (var i = 0; i < this.children.length; ++i)
+            this.children[i]._detach();
+    },
+
+    savePosition: function()
+    {
+        if (this._savedPosition)
+            return;
+
+        if (!this.parent)
+            throw("savePosition: Node must have a parent.");
+        this._savedPosition = {
+            parent: this.parent,
+            index: this.parent.children.indexOf(this)
+        };
+    },
+
+    restorePosition: function()
+    {
+        if (!this._savedPosition)
+            return;
+
+        if (this.parent !== this._savedPosition.parent)
+            this._savedPosition.parent.insertChild(this, this._savedPosition.index);
+
+        delete this._savedPosition;
+    }
+}
+
+WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.CreationDataGridNode = function(data, hasChildren)
+{
+    WebInspector.DataGridNode.call(this, data, hasChildren);
+    this.isCreationNode = true;
+}
+
+WebInspector.CreationDataGridNode.prototype = {
+    makeNormal: function()
+    {
+        delete this.isCreationNode;
+        delete this.makeNormal;
+    }
+}
+
+WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Database.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Database.js
new file mode 100644
index 0000000..effb809
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Database.js
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Database = function(id, domain, name, version)
+{
+    this._id = id;
+    this._domain = domain;
+    this._name = name;
+    this._version = version;
+}
+
+WebInspector.Database.prototype = {
+    get id()
+    {
+        return this._id;
+    },
+
+    get name()
+    {
+        return this._name;
+    },
+
+    set name(x)
+    {
+        this._name = x;
+    },
+
+    get version()
+    {
+        return this._version;
+    },
+
+    set version(x)
+    {
+        this._version = x;
+    },
+
+    get domain()
+    {
+        return this._domain;
+    },
+
+    set domain(x)
+    {
+        this._domain = x;
+    },
+
+    get displayDomain()
+    {
+        return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this);
+    },
+
+    getTableNames: function(callback)
+    {
+        function sortingCallback(names)
+        {
+            callback(names.sort());
+        }
+        InspectorBackend.getDatabaseTableNames(this._id, sortingCallback);
+    },
+    
+    executeSql: function(query, onSuccess, onError)
+    {
+        function callback(success, transactionId)
+        {
+            if (!success) {
+                onError(WebInspector.UIString("Database not found."));
+                return;
+            }
+            WebInspector.DatabaseDispatcher._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError};
+        }
+        InspectorBackend.executeSQL(this._id, query, callback);
+    }
+}
+
+WebInspector.DatabaseDispatcher = function()
+{
+}
+
+WebInspector.DatabaseDispatcher._callbacks = {};
+
+WebInspector.DatabaseDispatcher.prototype = {
+    addDatabase: function(payload)
+    {
+        var database = new WebInspector.Database(
+            payload.id,
+            payload.domain,
+            payload.name,
+            payload.version);
+        WebInspector.panels.resources.addDatabase(database);
+    },
+
+    selectDatabase: function(o)
+    {
+        WebInspector.showPanel("resources");
+        WebInspector.panels.resources.selectDatabase(o);
+    },
+
+    sqlTransactionSucceeded: function(transactionId, columnNames, values)
+    {
+        if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
+            return;
+    
+        var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId].onSuccess;
+        delete WebInspector.DatabaseDispatcher._callbacks[transactionId];
+        if (callback)
+            callback(columnNames, values);
+    },
+
+    sqlTransactionFailed: function(transactionId, errorObj)
+    {
+        if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
+            return;
+
+        var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId].onError;
+        delete WebInspector.DatabaseDispatcher._callbacks[transactionId];
+        if (callback)
+             callback(errorObj);
+    }
+}
+
+InspectorBackend.registerDomainDispatcher("Database", new WebInspector.DatabaseDispatcher());
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseQueryView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseQueryView.js
new file mode 100644
index 0000000..111246f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseQueryView.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseQueryView = function(database)
+{
+    WebInspector.View.call(this);
+
+    this.database = database;
+
+    this.element.addStyleClass("storage-view");
+    this.element.addStyleClass("query");
+    this.element.addStyleClass("monospace");
+    this.element.tabIndex = 0;
+
+    this.element.addEventListener("selectstart", this._selectStart.bind(this), false);
+
+    this.promptElement = document.createElement("div");
+    this.promptElement.className = "database-query-prompt";
+    this.promptElement.appendChild(document.createElement("br"));
+    this.promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
+    this.element.appendChild(this.promptElement);
+
+    this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " ");
+}
+
+WebInspector.DatabaseQueryView.prototype = {
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+
+        function moveBackIfOutside()
+        {
+            if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+                this.prompt.moveCaretToEndOfPrompt();
+        }
+
+        setTimeout(moveBackIfOutside.bind(this), 0);
+    },
+
+    completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
+    {
+        var prefix = wordRange.toString().toLowerCase();
+        if (!prefix.length)
+            return;
+
+        var results = [];
+
+        function accumulateMatches(textArray)
+        {
+            if (bestMatchOnly && results.length)
+                return;
+            for (var i = 0; i < textArray.length; ++i) {
+                var text = textArray[i].toLowerCase();
+                if (text.length < prefix.length)
+                    continue;
+                if (text.indexOf(prefix) !== 0)
+                    continue;
+                results.push(textArray[i]);
+                if (bestMatchOnly)
+                    return;
+            }
+        }
+        
+        function tableNamesCallback(tableNames)
+        {
+            accumulateMatches(tableNames.map(function(name) { return name + " " }));
+            accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
+
+            completionsReadyCallback(results);
+        }
+        this.database.getTableNames(tableNamesCallback);
+    },
+
+    _promptKeyDown: function(event)
+    {
+        if (isEnterKey(event)) {
+            this._enterKeyPressed(event);
+            return;
+        }
+    },
+
+    _selectStart: function(event)
+    {
+        if (this._selectionTimeout)
+            clearTimeout(this._selectionTimeout);
+
+        this.prompt.clearAutoComplete();
+
+        function moveBackIfOutside()
+        {
+            delete this._selectionTimeout;
+            if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+                this.prompt.moveCaretToEndOfPrompt();
+            this.prompt.autoCompleteSoon();
+        }
+
+        this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+    },
+
+    _enterKeyPressed: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+
+        this.prompt.clearAutoComplete(true);
+
+        var query = this.prompt.text;
+        if (!query.length)
+            return;
+
+        this.prompt.history.push(query);
+        this.prompt.historyOffset = 0;
+        this.prompt.text = "";
+
+        this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query));
+    },
+
+    _queryFinished: function(query, columnNames, values)
+    {
+        var dataGrid = WebInspector.panels.resources.dataGridForResult(columnNames, values);
+        var trimmedQuery = query.trim();
+
+        if (dataGrid) {
+            dataGrid.element.addStyleClass("inline");
+            this._appendQueryResult(trimmedQuery, dataGrid.element);
+            dataGrid.autoSizeColumns(5);            
+        }
+
+        if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
+            WebInspector.panels.resources.updateDatabaseTables(this.database);
+    },
+
+    _queryError: function(query, error)
+    {
+        if (error.message)
+            var message = error.message;
+        else if (error.code == 2)
+            var message = WebInspector.UIString("Database no longer has expected version.");
+        else
+            var message = WebInspector.UIString("An unexpected error %s occurred.", error.code);
+
+        this._appendQueryResult(query, message, "error");
+    },
+
+    _appendQueryResult: function(query, result, resultClassName)
+    {
+        var element = document.createElement("div");
+        element.className = "database-user-query";
+
+        var commandTextElement = document.createElement("span");
+        commandTextElement.className = "database-query-text";
+        commandTextElement.textContent = query;
+        element.appendChild(commandTextElement);
+
+        var resultElement = document.createElement("div");
+        resultElement.className = "database-query-result";
+
+        if (resultClassName)
+            resultElement.addStyleClass(resultClassName);
+
+        if (typeof result === "string" || result instanceof String)
+            resultElement.textContent = result;
+        else if (result && result.nodeName)
+            resultElement.appendChild(result);
+
+        if (resultElement.childNodes.length)
+            element.appendChild(resultElement);
+
+        this.element.insertBefore(element, this.promptElement);
+        this.promptElement.scrollIntoView(false);
+    }
+}
+
+WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseTableView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseTableView.js
new file mode 100644
index 0000000..1a886ff
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DatabaseTableView.js
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseTableView = function(database, tableName)
+{
+    WebInspector.View.call(this);
+
+    this.database = database;
+    this.tableName = tableName;
+
+    this.element.addStyleClass("storage-view");
+    this.element.addStyleClass("table");
+
+    this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
+    this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+}
+
+WebInspector.DatabaseTableView.prototype = {
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this.update();
+    },
+
+    get statusBarItems()
+    {
+        return [this.refreshButton.element];
+    },
+
+    update: function()
+    {
+        this.database.executeSql("SELECT * FROM " + this.tableName, this._queryFinished.bind(this), this._queryError.bind(this));
+    },
+
+    _queryFinished: function(columnNames, values)
+    {
+        this.element.removeChildren();
+
+        var dataGrid = WebInspector.panels.resources.dataGridForResult(columnNames, values);
+        if (!dataGrid) {
+            var emptyMsgElement = document.createElement("div");
+            emptyMsgElement.className = "storage-empty-view";
+            emptyMsgElement.textContent = WebInspector.UIString("The “%s”\ntable is empty.", this.tableName);
+            this.element.appendChild(emptyMsgElement);
+            return;
+        }
+
+        this.element.appendChild(dataGrid.element);
+        dataGrid.autoSizeColumns(5);
+    },
+
+    _queryError: function(error)
+    {
+        this.element.removeChildren();
+
+        var errorMsgElement = document.createElement("div");
+        errorMsgElement.className = "storage-table-error";
+        errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s” table.", this.tableName);
+        this.element.appendChild(errorMsgElement);
+    },
+
+    _refreshButtonClicked: function(event)
+    {
+        this.update();
+    }
+}
+
+WebInspector.DatabaseTableView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DebuggerModel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DebuggerModel.js
new file mode 100644
index 0000000..3384c34
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DebuggerModel.js
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DebuggerModel = function()
+{
+    this._paused = false;
+    this._callFrames = [];
+    this._breakpoints = {};
+    this._scripts = {};
+
+    InspectorBackend.registerDomainDispatcher("Debugger", new WebInspector.DebuggerDispatcher(this));
+}
+
+WebInspector.DebuggerModel.Events = {
+    DebuggerPaused: "debugger-paused",
+    DebuggerResumed: "debugger-resumed",
+    ParsedScriptSource: "parsed-script-source",
+    FailedToParseScriptSource: "failed-to-parse-script-source",
+    ScriptSourceChanged: "script-source-changed",
+    BreakpointAdded: "breakpoint-added",
+    BreakpointRemoved: "breakpoint-removed",
+    BreakpointResolved: "breakpoint-resolved"
+}
+
+WebInspector.DebuggerModel.prototype = {
+    enableDebugger: function()
+    {
+        InspectorBackend.enableDebugger();
+        if (this._breakpointsPushedToBackend)
+            return;
+        var breakpoints = WebInspector.settings.breakpoints;
+        for (var i = 0; i < breakpoints.length; ++i) {
+            var breakpoint = breakpoints[i];
+            if (typeof breakpoint.url !== "string" || typeof breakpoint.lineNumber !== "number" || typeof breakpoint.columnNumber !== "number" ||
+                typeof breakpoint.condition !== "string" || typeof breakpoint.enabled !== "boolean")
+                continue;
+            this.setBreakpoint(breakpoint.url, breakpoint.lineNumber, breakpoint.columnNumber, breakpoint.condition, breakpoint.enabled);
+        }
+        this._breakpointsPushedToBackend = true;
+    },
+
+    disableDebugger: function()
+    {
+        InspectorBackend.disableDebugger();
+    },
+
+    continueToLocation: function(sourceID, lineNumber, columnNumber)
+    {
+        InspectorBackend.continueToLocation(sourceID, lineNumber, columnNumber);
+    },
+
+    setBreakpoint: function(url, lineNumber, columnNumber, condition, enabled)
+    {
+        function didSetBreakpoint(breakpointsPushedToBackend, breakpointId, locations)
+        {
+            if (!breakpointId)
+                return;
+            var breakpoint = new WebInspector.Breakpoint(breakpointId, url, "", lineNumber, columnNumber, condition, enabled);
+            breakpoint.locations = locations;
+            this._breakpoints[breakpointId] = breakpoint;
+            if (breakpointsPushedToBackend)
+                this._saveBreakpoints();
+            this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
+        }
+        InspectorBackend.setJavaScriptBreakpoint(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this, this._breakpointsPushedToBackend));
+    },
+
+    setBreakpointBySourceId: function(sourceID, lineNumber, columnNumber, condition, enabled)
+    {
+        function didSetBreakpoint(breakpointId, actualLineNumber, actualColumnNumber)
+        {
+            if (!breakpointId)
+                return;
+            var breakpoint = new WebInspector.Breakpoint(breakpointId, "", sourceID, lineNumber, columnNumber, condition, enabled);
+            breakpoint.addLocation(sourceID, actualLineNumber, actualColumnNumber);
+            this._breakpoints[breakpointId] = breakpoint;
+            this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
+        }
+        InspectorBackend.setJavaScriptBreakpointBySourceId(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this));
+    },
+
+    removeBreakpoint: function(breakpointId)
+    {
+        InspectorBackend.removeJavaScriptBreakpoint(breakpointId);
+        var breakpoint = this._breakpoints[breakpointId];
+        delete this._breakpoints[breakpointId];
+        this._saveBreakpoints();
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointRemoved, breakpointId);
+    },
+
+    updateBreakpoint: function(breakpointId, condition, enabled)
+    {
+        var breakpoint = this._breakpoints[breakpointId];
+        this.removeBreakpoint(breakpointId);
+        if (breakpoint.url)
+            this.setBreakpoint(breakpoint.url, breakpoint.lineNumber, breakpoint.columnNumber, condition, enabled);
+        else
+            this.setBreakpointBySourceId(breakpoint.sourceID, breakpoint.lineNumber, breakpoint.columnNumber, condition, enabled);
+    },
+
+    _breakpointResolved: function(breakpointId, sourceID, lineNumber, columnNumber)
+    {
+        var breakpoint = this._breakpoints[breakpointId];
+        if (!breakpoint)
+            return;
+        breakpoint.addLocation(sourceID, lineNumber, columnNumber);
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, breakpoint);
+    },
+
+    _saveBreakpoints: function()
+    {
+        var serializedBreakpoints = [];
+        for (var id in this._breakpoints) {
+            var breakpoint = this._breakpoints[id];
+            if (!breakpoint.url)
+                continue;
+            var serializedBreakpoint = {};
+            serializedBreakpoint.url = breakpoint.url;
+            serializedBreakpoint.lineNumber = breakpoint.lineNumber;
+            serializedBreakpoint.columnNumber = breakpoint.columnNumber;
+            serializedBreakpoint.condition = breakpoint.condition;
+            serializedBreakpoint.enabled = breakpoint.enabled;
+            serializedBreakpoints.push(serializedBreakpoint);
+        }
+        WebInspector.settings.breakpoints = serializedBreakpoints;
+    },
+
+    get breakpoints()
+    {
+        return this._breakpoints;
+    },
+
+    breakpointForId: function(breakpointId)
+    {
+        return this._breakpoints[breakpointId];
+    },
+
+    queryBreakpoints: function(filter)
+    {
+        var breakpoints = [];
+        for (var id in this._breakpoints) {
+           var breakpoint = this._breakpoints[id];
+           if (filter(breakpoint))
+               breakpoints.push(breakpoint);
+        }
+        return breakpoints;
+    },
+
+    reset: function()
+    {
+        this._paused = false;
+        this._callFrames = [];
+        for (var id in this._breakpoints) {
+            var breakpoint = this._breakpoints[id];
+            if (!breakpoint.url)
+                this.removeBreakpoint(id);
+            else
+                breakpoint.locations = [];
+        }
+        this._scripts = {};
+    },
+
+    scriptForSourceID: function(sourceID)
+    {
+        return this._scripts[sourceID];
+    },
+
+    scriptsForURL: function(url)
+    {
+        return this.queryScripts(function(s) { return s.sourceURL === url; });
+    },
+
+    queryScripts: function(filter)
+    {
+        var scripts = [];
+        for (var sourceID in this._scripts) {
+            var script = this._scripts[sourceID];
+            if (filter(script))
+                scripts.push(script);
+        }
+        return scripts;
+    },
+
+    editScriptSource: function(sourceID, scriptSource)
+    {
+        function didEditScriptSource(success, newBodyOrErrorMessage, callFrames)
+        {
+            if (success) {
+                if (callFrames && callFrames.length)
+                    this._callFrames = callFrames;
+                this._updateScriptSource(sourceID, newBodyOrErrorMessage);
+            } else
+                WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Warning);
+        }
+        InspectorBackend.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
+    },
+
+    _updateScriptSource: function(sourceID, scriptSource)
+    {
+        var script = this._scripts[sourceID];
+        var oldSource = script.source;
+        script.source = scriptSource;
+
+        // Clear and re-create breakpoints according to text diff.
+        var diff = Array.diff(oldSource.split("\n"), script.source.split("\n"));
+        for (var id in this._breakpoints) {
+            var breakpoint = this._breakpoints[id];
+            if (breakpoint.url) {
+                if (breakpoint.url !== script.sourceURL)
+                    continue;
+            } else {
+                if (breakpoint.sourceID !== sourceID)
+                    continue;
+            }
+            this.removeBreakpoint(breakpoint.id);
+            var lineNumber = breakpoint.lineNumber;
+            var newLineNumber = diff.left[lineNumber].row;
+            if (newLineNumber === undefined) {
+                for (var i = lineNumber - 1; i >= 0; --i) {
+                    if (diff.left[i].row === undefined)
+                        continue;
+                    var shiftedLineNumber = diff.left[i].row + lineNumber - i;
+                    if (shiftedLineNumber < diff.right.length) {
+                        var originalLineNumber = diff.right[shiftedLineNumber].row;
+                        if (originalLineNumber === lineNumber || originalLineNumber === undefined)
+                            newLineNumber = shiftedLineNumber;
+                    }
+                    break;
+                }
+            }
+            if (newLineNumber === undefined)
+                continue;
+            if (breakpoint.url)
+                this.setBreakpoint(breakpoint.url, newLineNumber, breakpoint.columnNumber, breakpoint.condition, breakpoint.enabled);
+            else
+                this.setBreakpointBySourceId(sourceID, newLineNumber, breakpoint.columnNumber, breakpoint.condition, breakpoint.enabled);
+        }
+
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ScriptSourceChanged, { sourceID: sourceID, oldSource: oldSource });
+    },
+
+    get callFrames()
+    {
+        return this._callFrames;
+    },
+
+    _pausedScript: function(details)
+    {
+        this._paused = true;
+        this._callFrames = details.callFrames;
+        details.breakpoint = this._breakpointForCallFrame(details.callFrames[0]);
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
+    },
+
+    _resumedScript: function()
+    {
+        this._paused = false;
+        this._callFrames = [];
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
+    },
+
+    _breakpointForCallFrame: function(callFrame)
+    {
+        function match(location)
+        {
+            if (location.sourceID != callFrame.sourceID)
+                return false;
+            return location.lineNumber === callFrame.line && location.columnNumber === callFrame.column;
+        }
+        for (var id in this._breakpoints) {
+            var breakpoint = this._breakpoints[id];
+            for (var i = 0; i < breakpoint.locations.length; ++i) {
+                if (match(breakpoint.locations[i]))
+                    return breakpoint;
+            }
+        }
+    },
+
+    _parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType)
+    {
+        var script = new WebInspector.Script(sourceID, sourceURL, "", lineOffset, columnOffset, length, undefined, undefined, scriptWorldType);
+        this._scripts[sourceID] = script;
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script);
+    },
+
+    _failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
+    {
+        var script = new WebInspector.Script(null, sourceURL, source, startingLine, errorLine, errorMessage, undefined);
+        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script);
+    }
+}
+
+WebInspector.DebuggerModel.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DebuggerEventTypes = {
+    JavaScriptPause: 0,
+    JavaScriptBreakpoint: 1,
+    NativeBreakpoint: 2
+};
+
+WebInspector.DebuggerDispatcher = function(debuggerModel)
+{
+    this._debuggerModel = debuggerModel;
+}
+
+WebInspector.DebuggerDispatcher.prototype = {
+    pausedScript: function(details)
+    {
+        this._debuggerModel._pausedScript(details);
+    },
+
+    resumedScript: function()
+    {
+        this._debuggerModel._resumedScript();
+    },
+
+    debuggerWasEnabled: function()
+    {
+        WebInspector.panels.scripts.debuggerWasEnabled();
+    },
+
+    debuggerWasDisabled: function()
+    {
+        WebInspector.panels.scripts.debuggerWasDisabled();
+    },
+
+    parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType)
+    {
+        this._debuggerModel._parsedScriptSource(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType);
+    },
+
+    failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
+    {
+        this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage);
+    },
+
+    breakpointResolved: function(breakpointId, sourceID, lineNumber, columnNumber)
+    {
+        this._debuggerModel._breakpointResolved(breakpointId, sourceID, lineNumber, columnNumber);
+    },
+
+    didCreateWorker: function()
+    {
+        var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
+        workersPane.addWorker.apply(workersPane, arguments);
+    },
+
+    didDestroyWorker: function()
+    {
+        var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
+        workersPane.removeWorker.apply(workersPane, arguments);
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/DetailedHeapshotView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DetailedHeapshotView.js
new file mode 100644
index 0000000..5291bf2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/DetailedHeapshotView.js
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DetailedHeapshotView = function(parent, profile)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("heap-snapshot-view");
+
+    this.parent = parent;
+    this.profile = profile;
+}
+
+WebInspector.DetailedHeapshotView.prototype = {
+    get profile()
+    {
+        return this._profile;
+    },
+
+    set profile(profile)
+    {
+        this._profile = profile;
+    }
+};
+
+WebInspector.DetailedHeapshotView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.DetailedHeapshotProfileType = function()
+{
+    WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
+}
+
+WebInspector.DetailedHeapshotProfileType.prototype = {
+    get buttonTooltip()
+    {
+        return WebInspector.UIString("Take heap snapshot.");
+    },
+
+    get buttonStyle()
+    {
+        return "heap-snapshot-status-bar-item status-bar-item";
+    },
+
+    buttonClicked: function()
+    {
+        WebInspector.panels.profiles.takeHeapSnapshot(true);
+    },
+
+    get welcomeMessage()
+    {
+        return WebInspector.UIString("Get a heap snapshot by pressing the %s button on the status bar.");
+    },
+
+    createSidebarTreeElementForProfile: function(profile)
+    {
+        return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
+    },
+
+    createView: function(profile)
+    {
+        return new WebInspector.DetailedHeapshotView(WebInspector.panels.profiles, profile);
+    }
+}
+
+WebInspector.DetailedHeapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Drawer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Drawer.js
new file mode 100644
index 0000000..4861c90
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Drawer.js
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Drawer = function()
+{
+    WebInspector.View.call(this, document.getElementById("drawer"));
+
+    this._savedHeight = 200; // Default.
+    this.state = WebInspector.Drawer.State.Hidden;
+    this.fullPanel = false;
+
+    this._mainElement = document.getElementById("main");
+    this._toolbarElement = document.getElementById("toolbar");
+    this._mainStatusBar = document.getElementById("main-status-bar");
+    this._mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
+    this._viewStatusBar = document.getElementById("other-drawer-status-bar-items");
+    this._counters = document.getElementById("counters");
+    this._drawerStatusBar = document.getElementById("drawer-status-bar");
+}
+
+WebInspector.Drawer.prototype = {
+    get visibleView()
+    {
+        return this._visibleView;
+    },
+
+    set visibleView(x)
+    {
+        if (this._visibleView === x) {
+            if (this.visible && this.fullPanel)
+                return;
+            this.visible = !this.visible;
+            return;
+        }
+
+        var firstTime = !this._visibleView;
+        if (this._visibleView)
+            this._visibleView.hide();
+
+        this._visibleView = x;
+
+        if (x && !firstTime) {
+            this._safelyRemoveChildren();
+            this._viewStatusBar.removeChildren(); // optimize this? call old.detach()
+            x.attach(this.element, this._viewStatusBar);
+            x.show();
+            this.visible = true;
+        }
+    },
+
+    get savedHeight()
+    {
+        var height = this._savedHeight || this.element.offsetHeight;
+        return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+    },
+
+    showView: function(view)
+    {
+        if (!this.visible || this.visibleView !== view)
+            this.visibleView = view;
+    },
+
+    show: function()
+    {
+        if (this._animating || this.visible)
+            return;
+
+        if (this.visibleView)
+            this.visibleView.show();
+
+        WebInspector.View.prototype.show.call(this);
+
+        this._animating = true;
+
+        document.body.addStyleClass("drawer-visible");
+
+        var anchoredItems = document.getElementById("anchored-status-bar-items");
+        var height = (this.fullPanel ? window.innerHeight - this._toolbarElement.offsetHeight : this.savedHeight);
+        var animations = [
+            {element: this.element, end: {height: height}},
+            {element: this._mainElement, end: {bottom: height}},
+            {element: this._mainStatusBar, start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
+            {element: this._viewStatusBar, start: {opacity: 0}, end: {opacity: 1}}
+        ];
+
+        this._drawerStatusBar.insertBefore(anchoredItems, this._drawerStatusBar.firstChild);
+
+        if (this._currentPanelCounters) {
+            var oldRight = this._drawerStatusBar.clientWidth - (this._counters.offsetLeft + this._currentPanelCounters.offsetWidth);
+            var newRight = WebInspector.Panel.counterRightMargin;
+            var rightPadding = (oldRight - newRight);
+            animations.push({element: this._currentPanelCounters, start: {"padding-right": rightPadding}, end: {"padding-right": 0}});
+            this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters);
+            this._mainStatusBar.appendChild(this._currentPanelCounters);
+        }
+
+        function animationFinished()
+        {
+            if ("updateStatusBarItems" in WebInspector.currentPanel)
+                WebInspector.currentPanel.updateStatusBarItems();
+            if (this.visibleView.afterShow)
+                this.visibleView.afterShow();
+            delete this._animating;
+            delete this._currentAnimation;
+            this.state = (this.fullPanel ? WebInspector.Drawer.State.Full : WebInspector.Drawer.State.Variable);
+            if (this._currentPanelCounters)
+                this._currentPanelCounters.removeAttribute("style");
+        }
+
+        this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
+    },
+
+    hide: function()
+    {
+        if (this._animating || !this.visible)
+            return;
+
+        WebInspector.View.prototype.hide.call(this);
+
+        if (this.visibleView)
+            this.visibleView.hide();
+
+        this._animating = true;
+
+        if (!this.fullPanel)
+            this._savedHeight = this.element.offsetHeight;
+
+        if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
+            WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+
+        var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+        // Temporarily set properties and classes to mimic the post-animation values so panels
+        // like Elements in their updateStatusBarItems call will size things to fit the final location.
+        this._mainStatusBar.style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
+        document.body.removeStyleClass("drawer-visible");
+        if ("updateStatusBarItems" in WebInspector.currentPanel)
+            WebInspector.currentPanel.updateStatusBarItems();
+        document.body.addStyleClass("drawer-visible");
+
+        var animations = [
+            {element: this._mainElement, end: {bottom: 0}},
+            {element: this._mainStatusBar, start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
+            {element: this._viewStatusBar, start: {opacity: 1}, end: {opacity: 0}}
+        ];
+
+        if (this._currentPanelCounters) {
+            var newRight = this._drawerStatusBar.clientWidth - this._counters.offsetLeft;
+            var oldRight = this._mainStatusBar.clientWidth - (this._currentPanelCounters.offsetLeft + this._currentPanelCounters.offsetWidth);
+            var rightPadding = (newRight - oldRight);
+            animations.push({element: this._currentPanelCounters, start: {"padding-right": 0}, end: {"padding-right": rightPadding}});
+        }
+
+        function animationFinished()
+        {
+            WebInspector.currentPanel.resize();
+            this._mainStatusBar.insertBefore(anchoredItems, this._mainStatusBar.firstChild);
+            this._mainStatusBar.style.removeProperty("padding-left");
+
+            if (this._currentPanelCounters) {
+                this._currentPanelCounters.setAttribute("style", null);
+                this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters);
+                this._counters.insertBefore(this._currentPanelCounters, this._counters.firstChild);
+            }
+
+            document.body.removeStyleClass("drawer-visible");
+            delete this._animating;
+            delete this._currentAnimation;
+            this.state = WebInspector.Drawer.State.Hidden;
+        }
+
+        this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
+    },
+
+    resize: function()
+    {
+        if (this.state === WebInspector.Drawer.State.Hidden)
+            return;
+
+        var height;
+        if (this.state === WebInspector.Drawer.State.Variable) {
+            height = parseInt(this.element.style.height);
+            height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+        } else
+            height = window.innerHeight - this._toolbarElement.offsetHeight;
+
+        this._mainElement.style.bottom = height + "px";
+        this.element.style.height = height + "px";
+    },
+
+    enterPanelMode: function()
+    {
+        this._cancelAnimationIfNeeded();
+        this.fullPanel = true;
+        
+        if (this.visible) {
+            this._savedHeight = this.element.offsetHeight;
+            var height = window.innerHeight - this._toolbarElement.offsetHeight;
+            this._animateDrawerHeight(height, WebInspector.Drawer.State.Full);
+        }
+    },
+
+    exitPanelMode: function()
+    {
+        this._cancelAnimationIfNeeded();
+        this.fullPanel = false;
+
+        if (this.visible) {
+            // If this animation gets cancelled, we want the state of the drawer to be Variable,
+            // so that the new animation can't do an immediate transition between Hidden/Full states.
+            this.state = WebInspector.Drawer.State.Variable;
+            var height = this.savedHeight;
+            this._animateDrawerHeight(height, WebInspector.Drawer.State.Variable);
+        }
+    },
+
+    immediatelyExitPanelMode: function()
+    {
+        this.visible = false;
+        this.fullPanel = false;
+    },
+
+    immediatelyFinishAnimation: function()
+    {
+        if (this._currentAnimation)
+            this._currentAnimation.forceComplete();
+    },
+
+    set currentPanelCounters(x)
+    {
+        if (!x) {
+            if (this._currentPanelCounters)
+                this._currentPanelCounters.parentElement.removeChild(this._currentPanelCounters);
+            delete this._currentPanelCounters;
+            return;
+        }
+
+        this._currentPanelCounters = x;
+        if (this.visible)
+            this._mainStatusBar.appendChild(x);
+        else
+            this._counters.insertBefore(x, this._counters.firstChild);
+    },
+
+    _cancelAnimationIfNeeded: function()
+    {
+        if (this._animating) {
+            if (this._currentAnimation)
+                this._currentAnimation.cancel();
+            delete this._animating;
+            delete this._currentAnimation;
+        }
+    },
+
+    _animateDrawerHeight: function(height, finalState)
+    {
+        this._animating = true;
+        var animations = [
+            {element: this.element, end: {height: height}},
+            {element: this._mainElement, end: {bottom: height}}
+        ];
+
+        function animationFinished()
+        {
+            delete this._animating;
+            delete this._currentAnimation;
+            this.state = finalState;
+        }
+
+        this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
+    },
+
+    _animationDuration: function()
+    {
+        // Immediate if going between Hidden and Full in full panel mode
+        if (this.fullPanel && (this.state === WebInspector.Drawer.State.Hidden || this.state === WebInspector.Drawer.State.Full))
+            return 0;
+
+        return (window.event && window.event.shiftKey ? 2000 : 250);
+    },
+
+    _safelyRemoveChildren: function()
+    {
+        var child = this.element.firstChild;
+        while (child) {
+            if (child.id !== "drawer-status-bar") {
+                var moveTo = child.nextSibling;
+                this.element.removeChild(child);
+                child = moveTo;
+            } else
+                child = child.nextSibling;
+        }
+    },
+
+    _startStatusBarDragging: function(event)
+    {
+        if (!this.visible || event.target !== this._mainStatusBar)
+            return;
+
+        WebInspector.elementDragStart(this._mainStatusBar, this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");
+
+        this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;
+
+        event.stopPropagation();
+    },
+
+    _statusBarDragging: function(event)
+    {
+        var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
+        height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+
+        this._mainElement.style.bottom = height + "px";
+        this.element.style.height = height + "px";
+
+        event.preventDefault();
+        event.stopPropagation();
+    },
+
+    _endStatusBarDragging: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+
+        this._savedHeight = this.element.offsetHeight;
+        delete this._statusBarDragOffset;
+
+        event.stopPropagation();
+    }
+}
+
+WebInspector.Drawer.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.Drawer.State = {
+    Hidden: 0,
+    Variable: 1,
+    Full: 2
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsPanel.js
new file mode 100644
index 0000000..e6af93c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsPanel.js
@@ -0,0 +1,1087 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsPanel = function()
+{
+    WebInspector.Panel.call(this, "elements");
+
+    this.contentElement = document.createElement("div");
+    this.contentElement.id = "elements-content";
+    this.contentElement.className = "outline-disclosure source-code";
+
+    this.treeOutline = new WebInspector.ElementsTreeOutline();
+    this.treeOutline.panel = this;
+    this.treeOutline.includeRootDOMNode = false;
+    this.treeOutline.selectEnabled = true;
+
+    this.treeOutline.focusedNodeChanged = function(forceUpdate)
+    {
+        if (this.panel.visible && WebInspector.currentFocusElement !== document.getElementById("search"))
+            WebInspector.currentFocusElement = this.element;
+
+        this.panel.updateBreadcrumb(forceUpdate);
+
+        for (var pane in this.panel.sidebarPanes)
+           this.panel.sidebarPanes[pane].needsUpdate = true;
+
+        this.panel.updateStyles(true);
+        this.panel.updateMetrics();
+        this.panel.updateProperties();
+        this.panel.updateEventListeners();
+
+        if (this._focusedDOMNode) {
+            InspectorBackend.addInspectedNode(this._focusedDOMNode.id);
+            WebInspector.extensionServer.notifyObjectSelected(this.panel.name);
+        }
+    };
+
+    this.contentElement.appendChild(this.treeOutline.element);
+
+    this.crumbsElement = document.createElement("div");
+    this.crumbsElement.className = "crumbs";
+    this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false);
+    this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false);
+
+    this.sidebarPanes = {};
+    this.sidebarPanes.computedStyle = new WebInspector.ComputedStyleSidebarPane();
+    this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(this.sidebarPanes.computedStyle);
+    this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
+    this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
+    if (Preferences.nativeInstrumentationEnabled)
+        this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane();
+    this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane();
+
+    this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
+    this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
+    this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
+    this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this);
+
+    this.sidebarPanes.styles.expanded = true;
+
+    this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this);
+    this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this);
+    this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this);
+    WebInspector.cssModel.addEventListener("stylesheet changed", this._styleSheetChanged, this);
+
+    this.sidebarElement = document.createElement("div");
+    this.sidebarElement.id = "elements-sidebar";
+
+    for (var pane in this.sidebarPanes)
+        this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
+
+    this.sidebarResizeElement = document.createElement("div");
+    this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+    this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
+
+    this._nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item");
+    this._nodeSearchButton.addEventListener("click", this.toggleSearchingForNode.bind(this), false);
+
+    this.element.appendChild(this.contentElement);
+    this.element.appendChild(this.sidebarElement);
+    this.element.appendChild(this.sidebarResizeElement);
+
+    this._registerShortcuts();
+
+    this.reset();
+}
+
+WebInspector.ElementsPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Elements");
+    },
+
+    get statusBarItems()
+    {
+        return [this._nodeSearchButton.element, this.crumbsElement];
+    },
+
+    get defaultFocusedElement()
+    {
+        return this.treeOutline.element;
+    },
+
+    updateStatusBarItems: function()
+    {
+        this.updateBreadcrumbSizes();
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+        this.updateBreadcrumb();
+        this.treeOutline.updateSelection();
+        if (this.recentlyModifiedNodes.length)
+            this.updateModifiedNodes();
+    },
+
+    hide: function()
+    {
+        WebInspector.Panel.prototype.hide.call(this);
+
+        WebInspector.highlightDOMNode(0);
+        this.setSearchingForNode(false);
+    },
+
+    resize: function()
+    {
+        this.treeOutline.updateSelection();
+        this.updateBreadcrumbSizes();
+    },
+
+    reset: function()
+    {
+        if (this.focusedDOMNode)
+            this._selectedPathOnReset = this.focusedDOMNode.path();
+
+        this.rootDOMNode = null;
+        this.focusedDOMNode = null;
+
+        WebInspector.highlightDOMNode(0);
+
+        this.recentlyModifiedNodes = [];
+
+        delete this.currentQuery;
+    },
+
+    setDocument: function(inspectedRootDocument)
+    {
+        this.reset();
+        this.searchCanceled();
+
+        if (!inspectedRootDocument)
+            return;
+
+        inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this));
+        inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this));
+        inspectedRootDocument.addEventListener("DOMAttrModified", this._attributesUpdated.bind(this));
+        inspectedRootDocument.addEventListener("DOMCharacterDataModified", this._characterDataModified.bind(this));
+
+        this.rootDOMNode = inspectedRootDocument;
+
+        function selectNode(candidateFocusNode)
+        {
+            if (!candidateFocusNode)
+                candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;
+
+            if (!candidateFocusNode)
+                return;
+
+            this.focusedDOMNode = candidateFocusNode;
+            if (this.treeOutline.selectedTreeElement)
+                this.treeOutline.selectedTreeElement.expand();
+        }
+
+        function selectLastSelectedNode(nodeId)
+        {
+            if (this.focusedDOMNode) {
+                // Focused node has been explicitly set while reaching out for the last selected node.
+                return;
+            }
+            var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : 0;
+            selectNode.call(this, node);
+        }
+
+        if (this._selectedPathOnReset)
+            InspectorBackend.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
+        else
+            selectNode.call(this);
+        delete this._selectedPathOnReset;
+    },
+
+    searchCanceled: function()
+    {
+        delete this._searchQuery;
+        this._hideSearchHighlights();
+
+        WebInspector.updateSearchMatchesCount(0, this);
+
+        this._currentSearchResultIndex = 0;
+        this._searchResults = [];
+        InspectorBackend.searchCanceled();
+    },
+
+    performSearch: function(query)
+    {
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled();
+
+        const whitespaceTrimmedQuery = query.trim();
+        if (!whitespaceTrimmedQuery.length)
+            return;
+
+        this._updatedMatchCountOnce = false;
+        this._matchesCountUpdateTimeout = null;
+        this._searchQuery = query;
+
+        InspectorBackend.performSearch(whitespaceTrimmedQuery, false);
+    },
+
+    populateHrefContextMenu: function(contextMenu, event, anchorElement)
+    {
+        if (!anchorElement.href)
+            return false;
+
+        var resourceURL = WebInspector.resourceURLForRelatedNode(this.focusedDOMNode, anchorElement.href);
+        if (!resourceURL)
+            return false;
+
+        // Add resource-related actions.
+        contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(null, resourceURL, false));
+        if (WebInspector.resourceForURL(resourceURL))
+            contextMenu.appendItem(WebInspector.UIString("Open Link in Resources Panel"), WebInspector.openResource.bind(null, resourceURL, true));
+        return true;
+    },
+
+    switchToAndFocus: function(node)
+    {
+        // Reset search restore.
+        WebInspector.cancelSearch();
+        WebInspector.currentPanel = this;
+        this.focusedDOMNode = node;
+    },
+
+    _updateMatchesCount: function()
+    {
+        WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+        this._matchesCountUpdateTimeout = null;
+        this._updatedMatchCountOnce = true;
+    },
+
+    _updateMatchesCountSoon: function()
+    {
+        if (!this._updatedMatchCountOnce)
+            return this._updateMatchesCount();
+        if (this._matchesCountUpdateTimeout)
+            return;
+        // Update the matches count every half-second so it doesn't feel twitchy.
+        this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500);
+    },
+
+    addNodesToSearchResult: function(nodeIds)
+    {
+        if (!nodeIds.length)
+            return;
+
+        for (var i = 0; i < nodeIds.length; ++i) {
+            var nodeId = nodeIds[i];
+            var node = WebInspector.domAgent.nodeForId(nodeId);
+            if (!node)
+                continue;
+
+            this._currentSearchResultIndex = 0;
+            this._searchResults.push(node);
+        }
+        this._highlightCurrentSearchResult();
+        this._updateMatchesCountSoon();
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+
+        if (++this._currentSearchResultIndex >= this._searchResults.length)
+            this._currentSearchResultIndex = 0;
+        this._highlightCurrentSearchResult();
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+
+        if (--this._currentSearchResultIndex < 0)
+            this._currentSearchResultIndex = (this._searchResults.length - 1);
+        this._highlightCurrentSearchResult();
+    },
+
+    _highlightCurrentSearchResult: function()
+    {
+        this._hideSearchHighlights();
+        var node = this._searchResults[this._currentSearchResultIndex];
+        var treeElement = this.treeOutline.findTreeElement(node);
+        if (treeElement) {
+            treeElement.highlightSearchResults(this._searchQuery);
+            treeElement.reveal();
+        }
+    },
+
+    _hideSearchHighlights: function(node)
+    {
+        for (var i = 0; this._searchResults && i < this._searchResults.length; ++i) {
+            var node = this._searchResults[i];
+            var treeElement = this.treeOutline.findTreeElement(node);
+            if (treeElement)
+                treeElement.highlightSearchResults(null);
+        }
+    },
+
+    renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector)
+    {
+        // TODO: Implement Shifting the oldSelector, and its contents to a newSelector
+    },
+
+    get rootDOMNode()
+    {
+        return this.treeOutline.rootDOMNode;
+    },
+
+    set rootDOMNode(x)
+    {
+        this.treeOutline.rootDOMNode = x;
+    },
+
+    get focusedDOMNode()
+    {
+        return this.treeOutline.focusedDOMNode;
+    },
+
+    set focusedDOMNode(x)
+    {
+        this.treeOutline.focusedDOMNode = x;
+    },
+
+    _attributesUpdated: function(event)
+    {
+        this.recentlyModifiedNodes.push({node: event.target, updated: true});
+        if (this.visible)
+            this._updateModifiedNodesSoon();
+    },
+
+    _characterDataModified: function(event)
+    {
+        this.recentlyModifiedNodes.push({node: event.target, updated: true});
+        if (this.visible)
+            this._updateModifiedNodesSoon();
+    },
+
+    _nodeInserted: function(event)
+    {
+        this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true});
+        if (this.visible)
+            this._updateModifiedNodesSoon();
+    },
+
+    _nodeRemoved: function(event)
+    {
+        this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, removed: true});
+        if (this.visible)
+            this._updateModifiedNodesSoon();
+    },
+
+    _updateModifiedNodesSoon: function()
+    {
+        if ("_updateModifiedNodesTimeout" in this)
+            return;
+        this._updateModifiedNodesTimeout = setTimeout(this.updateModifiedNodes.bind(this), 0);
+    },
+
+    updateModifiedNodes: function()
+    {
+        if ("_updateModifiedNodesTimeout" in this) {
+            clearTimeout(this._updateModifiedNodesTimeout);
+            delete this._updateModifiedNodesTimeout;
+        }
+
+        var updatedParentTreeElements = [];
+        var updateBreadcrumbs = false;
+
+        for (var i = 0; i < this.recentlyModifiedNodes.length; ++i) {
+            var replaced = this.recentlyModifiedNodes[i].replaced;
+            var parent = this.recentlyModifiedNodes[i].parent;
+            var node = this.recentlyModifiedNodes[i].node;
+
+            if (this.recentlyModifiedNodes[i].updated) {
+                var nodeItem = this.treeOutline.findTreeElement(node);
+                if (nodeItem)
+                    nodeItem.updateTitle();
+                continue;
+            }
+            
+            if (!parent)
+                continue;
+
+            var parentNodeItem = this.treeOutline.findTreeElement(parent);
+            if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
+                parentNodeItem.updateChildren(replaced);
+                parentNodeItem.alreadyUpdatedChildren = true;
+                updatedParentTreeElements.push(parentNodeItem);
+            }
+
+            if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestorNode(this.focusedDOMNode, parent)))
+                updateBreadcrumbs = true;
+        }
+
+        for (var i = 0; i < updatedParentTreeElements.length; ++i)
+            delete updatedParentTreeElements[i].alreadyUpdatedChildren;
+
+        this.recentlyModifiedNodes = [];
+
+        if (updateBreadcrumbs)
+            this.updateBreadcrumb(true);
+    },
+
+    _stylesPaneEdited: function()
+    {
+        // Once styles are edited, the Metrics pane should be updated.
+        this.sidebarPanes.metrics.needsUpdate = true;
+        this.updateMetrics();
+    },
+
+    _metricsPaneEdited: function()
+    {
+        // Once metrics are edited, the Styles pane should be updated.
+        this.sidebarPanes.styles.needsUpdate = true;
+        this.updateStyles(true);
+    },
+
+    _styleSheetChanged: function()
+    {
+        this._metricsPaneEdited();
+        this._stylesPaneEdited();
+    },
+
+    _mouseMovedInCrumbs: function(event)
+    {
+        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+        var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb");
+
+        WebInspector.highlightDOMNode(crumbElement ? crumbElement.representedObject.id : 0);
+
+        if ("_mouseOutOfCrumbsTimeout" in this) {
+            clearTimeout(this._mouseOutOfCrumbsTimeout);
+            delete this._mouseOutOfCrumbsTimeout;
+        }
+    },
+
+    _mouseMovedOutOfCrumbs: function(event)
+    {
+        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+        if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.crumbsElement))
+            return;
+
+        WebInspector.highlightDOMNode(0);
+
+        this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000);
+    },
+
+    updateBreadcrumb: function(forceUpdate)
+    {
+        if (!this.visible)
+            return;
+
+        var crumbs = this.crumbsElement;
+
+        var handled = false;
+        var foundRoot = false;
+        var crumb = crumbs.firstChild;
+        while (crumb) {
+            if (crumb.representedObject === this.rootDOMNode)
+                foundRoot = true;
+
+            if (foundRoot)
+                crumb.addStyleClass("dimmed");
+            else
+                crumb.removeStyleClass("dimmed");
+
+            if (crumb.representedObject === this.focusedDOMNode) {
+                crumb.addStyleClass("selected");
+                handled = true;
+            } else {
+                crumb.removeStyleClass("selected");
+            }
+
+            crumb = crumb.nextSibling;
+        }
+
+        if (handled && !forceUpdate) {
+            // We don't need to rebuild the crumbs, but we need to adjust sizes
+            // to reflect the new focused or root node.
+            this.updateBreadcrumbSizes();
+            return;
+        }
+
+        crumbs.removeChildren();
+
+        var panel = this;
+
+        function selectCrumbFunction(event)
+        {
+            var crumb = event.currentTarget;
+            if (crumb.hasStyleClass("collapsed")) {
+                // Clicking a collapsed crumb will expose the hidden crumbs.
+                if (crumb === panel.crumbsElement.firstChild) {
+                    // If the focused crumb is the first child, pick the farthest crumb
+                    // that is still hidden. This allows the user to expose every crumb.
+                    var currentCrumb = crumb;
+                    while (currentCrumb) {
+                        var hidden = currentCrumb.hasStyleClass("hidden");
+                        var collapsed = currentCrumb.hasStyleClass("collapsed");
+                        if (!hidden && !collapsed)
+                            break;
+                        crumb = currentCrumb;
+                        currentCrumb = currentCrumb.nextSibling;
+                    }
+                }
+
+                panel.updateBreadcrumbSizes(crumb);
+            } else {
+                // Clicking a dimmed crumb or double clicking (event.detail >= 2)
+                // will change the root node in addition to the focused node.
+                if (event.detail >= 2 || crumb.hasStyleClass("dimmed"))
+                    panel.rootDOMNode = crumb.representedObject.parentNode;
+                panel.focusedDOMNode = crumb.representedObject;
+            }
+
+            event.preventDefault();
+        }
+
+        foundRoot = false;
+        for (var current = this.focusedDOMNode; current; current = current.parentNode) {
+            if (current.nodeType === Node.DOCUMENT_NODE)
+                continue;
+
+            if (current === this.rootDOMNode)
+                foundRoot = true;
+
+            var crumb = document.createElement("span");
+            crumb.className = "crumb";
+            crumb.representedObject = current;
+            crumb.addEventListener("mousedown", selectCrumbFunction, false);
+
+            var crumbTitle;
+            switch (current.nodeType) {
+                case Node.ELEMENT_NODE:
+                    this.decorateNodeLabel(current, crumb);
+                    break;
+
+                case Node.TEXT_NODE:
+                    if (isNodeWhitespace.call(current))
+                        crumbTitle = WebInspector.UIString("(whitespace)");
+                    else
+                        crumbTitle = WebInspector.UIString("(text)");
+                    break
+
+                case Node.COMMENT_NODE:
+                    crumbTitle = "<!-->";
+                    break;
+
+                case Node.DOCUMENT_TYPE_NODE:
+                    crumbTitle = "<!DOCTYPE>";
+                    break;
+
+                default:
+                    crumbTitle = this.treeOutline.nodeNameToCorrectCase(current.nodeName);
+            }
+
+            if (!crumb.childNodes.length) {
+                var nameElement = document.createElement("span");
+                nameElement.textContent = crumbTitle;
+                crumb.appendChild(nameElement);
+                crumb.title = crumbTitle;
+            }
+
+            if (foundRoot)
+                crumb.addStyleClass("dimmed");
+            if (current === this.focusedDOMNode)
+                crumb.addStyleClass("selected");
+            if (!crumbs.childNodes.length)
+                crumb.addStyleClass("end");
+
+            crumbs.appendChild(crumb);
+        }
+
+        if (crumbs.hasChildNodes())
+            crumbs.lastChild.addStyleClass("start");
+
+        this.updateBreadcrumbSizes();
+    },
+
+    decorateNodeLabel: function(node, parentElement)
+    {
+        var title = this.treeOutline.nodeNameToCorrectCase(node.nodeName);
+
+        var nameElement = document.createElement("span");
+        nameElement.textContent = title;
+        parentElement.appendChild(nameElement);
+
+        var idAttribute = node.getAttribute("id");
+        if (idAttribute) {
+            var idElement = document.createElement("span");
+            parentElement.appendChild(idElement);
+
+            var part = "#" + idAttribute;
+            title += part;
+            idElement.appendChild(document.createTextNode(part));
+
+            // Mark the name as extra, since the ID is more important.
+            nameElement.className = "extra";
+        }
+
+        var classAttribute = node.getAttribute("class");
+        if (classAttribute) {
+            var classes = classAttribute.split(/\s+/);
+            var foundClasses = {};
+
+            if (classes.length) {
+                var classesElement = document.createElement("span");
+                classesElement.className = "extra";
+                parentElement.appendChild(classesElement);
+
+                for (var i = 0; i < classes.length; ++i) {
+                    var className = classes[i];
+                    if (className && !(className in foundClasses)) {
+                        var part = "." + className;
+                        title += part;
+                        classesElement.appendChild(document.createTextNode(part));
+                        foundClasses[className] = true;
+                    }
+                }
+            }
+        }
+        parentElement.title = title;
+    },
+
+    linkifyNodeReference: function(node)
+    {
+        var link = document.createElement("span");
+        link.className = "node-link";
+        this.decorateNodeLabel(node, link);
+        WebInspector.wireElementWithDOMNode(link, node.id);
+        return link;
+    },
+
+    linkifyNodeById: function(nodeId)
+    {
+        var node = WebInspector.domAgent.nodeForId(nodeId);
+        if (!node)
+            return document.createTextNode(WebInspector.UIString("<node>"));
+        return this.linkifyNodeReference(node);
+    },
+
+    updateBreadcrumbSizes: function(focusedCrumb)
+    {
+        if (!this.visible)
+            return;
+
+        if (document.body.offsetWidth <= 0) {
+            // The stylesheet hasn't loaded yet or the window is closed,
+            // so we can't calculate what is need. Return early.
+            return;
+        }
+
+        var crumbs = this.crumbsElement;
+        if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0)
+            return; // No crumbs, do nothing.
+
+        // A Zero index is the right most child crumb in the breadcrumb.
+        var selectedIndex = 0;
+        var focusedIndex = 0;
+        var selectedCrumb;
+
+        var i = 0;
+        var crumb = crumbs.firstChild;
+        while (crumb) {
+            // Find the selected crumb and index. 
+            if (!selectedCrumb && crumb.hasStyleClass("selected")) {
+                selectedCrumb = crumb;
+                selectedIndex = i;
+            }
+
+            // Find the focused crumb index. 
+            if (crumb === focusedCrumb)
+                focusedIndex = i;
+
+            // Remove any styles that affect size before
+            // deciding to shorten any crumbs.
+            if (crumb !== crumbs.lastChild)
+                crumb.removeStyleClass("start");
+            if (crumb !== crumbs.firstChild)
+                crumb.removeStyleClass("end");
+
+            crumb.removeStyleClass("compact");
+            crumb.removeStyleClass("collapsed");
+            crumb.removeStyleClass("hidden");
+
+            crumb = crumb.nextSibling;
+            ++i;
+        }
+
+        // Restore the start and end crumb classes in case they got removed in coalesceCollapsedCrumbs().
+        // The order of the crumbs in the document is opposite of the visual order.
+        crumbs.firstChild.addStyleClass("end");
+        crumbs.lastChild.addStyleClass("start");
+
+        function crumbsAreSmallerThanContainer()
+        {
+            var rightPadding = 20;
+            var errorWarningElement = document.getElementById("error-warning-count");
+            if (!WebInspector.drawer.visible && errorWarningElement)
+                rightPadding += errorWarningElement.offsetWidth;
+            return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth);
+        }
+
+        if (crumbsAreSmallerThanContainer())
+            return; // No need to compact the crumbs, they all fit at full size.
+
+        var BothSides = 0;
+        var AncestorSide = -1;
+        var ChildSide = 1;
+
+        function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb)
+        {
+            if (!significantCrumb)
+                significantCrumb = (focusedCrumb || selectedCrumb);
+
+            if (significantCrumb === selectedCrumb)
+                var significantIndex = selectedIndex;
+            else if (significantCrumb === focusedCrumb)
+                var significantIndex = focusedIndex;
+            else {
+                var significantIndex = 0;
+                for (var i = 0; i < crumbs.childNodes.length; ++i) {
+                    if (crumbs.childNodes[i] === significantCrumb) {
+                        significantIndex = i;
+                        break;
+                    }
+                }
+            }
+
+            function shrinkCrumbAtIndex(index)
+            {
+                var shrinkCrumb = crumbs.childNodes[index];
+                if (shrinkCrumb && shrinkCrumb !== significantCrumb)
+                    shrinkingFunction(shrinkCrumb);
+                if (crumbsAreSmallerThanContainer())
+                    return true; // No need to compact the crumbs more.
+                return false;
+            }
+
+            // Shrink crumbs one at a time by applying the shrinkingFunction until the crumbs
+            // fit in the container or we run out of crumbs to shrink.
+            if (direction) {
+                // Crumbs are shrunk on only one side (based on direction) of the signifcant crumb.
+                var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1);
+                while (index !== significantIndex) {
+                    if (shrinkCrumbAtIndex(index))
+                        return true;
+                    index += (direction > 0 ? 1 : -1);
+                }
+            } else {
+                // Crumbs are shrunk in order of descending distance from the signifcant crumb,
+                // with a tie going to child crumbs.
+                var startIndex = 0;
+                var endIndex = crumbs.childNodes.length - 1;
+                while (startIndex != significantIndex || endIndex != significantIndex) {
+                    var startDistance = significantIndex - startIndex;
+                    var endDistance = endIndex - significantIndex;
+                    if (startDistance >= endDistance)
+                        var index = startIndex++;
+                    else
+                        var index = endIndex--;
+                    if (shrinkCrumbAtIndex(index))
+                        return true;
+                }
+            }
+
+            // We are not small enough yet, return false so the caller knows.
+            return false;
+        }
+
+        function coalesceCollapsedCrumbs()
+        {
+            var crumb = crumbs.firstChild;
+            var collapsedRun = false;
+            var newStartNeeded = false;
+            var newEndNeeded = false;
+            while (crumb) {
+                var hidden = crumb.hasStyleClass("hidden");
+                if (!hidden) {
+                    var collapsed = crumb.hasStyleClass("collapsed"); 
+                    if (collapsedRun && collapsed) {
+                        crumb.addStyleClass("hidden");
+                        crumb.removeStyleClass("compact");
+                        crumb.removeStyleClass("collapsed");
+
+                        if (crumb.hasStyleClass("start")) {
+                            crumb.removeStyleClass("start");
+                            newStartNeeded = true;
+                        }
+
+                        if (crumb.hasStyleClass("end")) {
+                            crumb.removeStyleClass("end");
+                            newEndNeeded = true;
+                        }
+
+                        continue;
+                    }
+
+                    collapsedRun = collapsed;
+
+                    if (newEndNeeded) {
+                        newEndNeeded = false;
+                        crumb.addStyleClass("end");
+                    }
+                } else
+                    collapsedRun = true;
+                crumb = crumb.nextSibling;
+            }
+
+            if (newStartNeeded) {
+                crumb = crumbs.lastChild;
+                while (crumb) {
+                    if (!crumb.hasStyleClass("hidden")) {
+                        crumb.addStyleClass("start");
+                        break;
+                    }
+                    crumb = crumb.previousSibling;
+                }
+            }
+        }
+
+        function compact(crumb)
+        {
+            if (crumb.hasStyleClass("hidden"))
+                return;
+            crumb.addStyleClass("compact");
+        }
+
+        function collapse(crumb, dontCoalesce)
+        {
+            if (crumb.hasStyleClass("hidden"))
+                return;
+            crumb.addStyleClass("collapsed");
+            crumb.removeStyleClass("compact");
+            if (!dontCoalesce)
+                coalesceCollapsedCrumbs();
+        }
+
+        function compactDimmed(crumb)
+        {
+            if (crumb.hasStyleClass("dimmed"))
+                compact(crumb);
+        }
+
+        function collapseDimmed(crumb)
+        {
+            if (crumb.hasStyleClass("dimmed"))
+                collapse(crumb);
+        }
+
+        if (!focusedCrumb) {
+            // When not focused on a crumb we can be biased and collapse less important
+            // crumbs that the user might not care much about.
+
+            // Compact child crumbs.
+            if (makeCrumbsSmaller(compact, ChildSide))
+                return;
+
+            // Collapse child crumbs.
+            if (makeCrumbsSmaller(collapse, ChildSide))
+                return;
+
+            // Compact dimmed ancestor crumbs.
+            if (makeCrumbsSmaller(compactDimmed, AncestorSide))
+                return;
+
+            // Collapse dimmed ancestor crumbs.
+            if (makeCrumbsSmaller(collapseDimmed, AncestorSide))
+                return;
+        }
+
+        // Compact ancestor crumbs, or from both sides if focused.
+        if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide)))
+            return;
+
+        // Collapse ancestor crumbs, or from both sides if focused.
+        if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide)))
+            return;
+
+        if (!selectedCrumb)
+            return;
+
+        // Compact the selected crumb.
+        compact(selectedCrumb);
+        if (crumbsAreSmallerThanContainer())
+            return;
+
+        // Collapse the selected crumb as a last resort. Pass true to prevent coalescing.
+        collapse(selectedCrumb, true);
+    },
+
+    updateStyles: function(forceUpdate)
+    {
+        var stylesSidebarPane = this.sidebarPanes.styles;
+        var computedStylePane = this.sidebarPanes.computedStyle;
+        if ((!stylesSidebarPane.expanded && !computedStylePane.expanded) || !stylesSidebarPane.needsUpdate)
+            return;
+
+        stylesSidebarPane.update(this.focusedDOMNode, null, forceUpdate);
+        stylesSidebarPane.needsUpdate = false;
+    },
+
+    updateMetrics: function()
+    {
+        var metricsSidebarPane = this.sidebarPanes.metrics;
+        if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
+            return;
+
+        metricsSidebarPane.update(this.focusedDOMNode);
+        metricsSidebarPane.needsUpdate = false;
+    },
+
+    updateProperties: function()
+    {
+        var propertiesSidebarPane = this.sidebarPanes.properties;
+        if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
+            return;
+
+        propertiesSidebarPane.update(this.focusedDOMNode);
+        propertiesSidebarPane.needsUpdate = false;
+    },
+
+    updateEventListeners: function()
+    {
+        var eventListenersSidebarPane = this.sidebarPanes.eventListeners;
+        if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate)
+            return;
+
+        eventListenersSidebarPane.update(this.focusedDOMNode);
+        eventListenersSidebarPane.needsUpdate = false;
+    },
+
+    _registerShortcuts: function()
+    {
+        var shortcut = WebInspector.KeyboardShortcut;
+        var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Elements Panel"));
+        var keys = [
+            shortcut.shortcutToString(shortcut.Keys.Up),
+            shortcut.shortcutToString(shortcut.Keys.Down)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Navigate elements"));
+        var keys = [
+            shortcut.shortcutToString(shortcut.Keys.Right),
+            shortcut.shortcutToString(shortcut.Keys.Left)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Expand/collapse"));
+        section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Edit attribute"));
+
+        this.sidebarPanes.styles.registerShortcuts();
+    },
+
+    handleShortcut: function(event)
+    {
+        // Cmd/Control + Shift + C should be a shortcut to clicking the Node Search Button.
+        // This shortcut matches Firebug.
+        if (event.keyIdentifier === "U+0043") {     // C key
+            if (WebInspector.isMac())
+                var isNodeSearchKey = event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey;
+            else
+                var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey;
+
+            if (isNodeSearchKey) {
+                this.toggleSearchingForNode();
+                event.handled = true;
+                return;
+            }
+        }
+    },
+
+    handleCopyEvent: function(event)
+    {
+        // Don't prevent the normal copy if the user has a selection.
+        if (!window.getSelection().isCollapsed)
+            return;
+        event.clipboardData.clearData();
+        event.preventDefault();
+        InspectorBackend.copyNode(this.focusedDOMNode.id);
+    },
+
+    rightSidebarResizerDragStart: function(event)
+    {
+        WebInspector.elementDragStart(this.sidebarElement, this.rightSidebarResizerDrag.bind(this), this.rightSidebarResizerDragEnd.bind(this), event, "col-resize");
+    },
+
+    rightSidebarResizerDragEnd: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+        this.saveSidebarWidth();
+    },
+
+    rightSidebarResizerDrag: function(event)
+    {
+        var x = event.pageX;
+        var newWidth = Number.constrain(window.innerWidth - x, Preferences.minElementsSidebarWidth, window.innerWidth * 0.66);
+        this.setSidebarWidth(newWidth);
+        event.preventDefault();
+    },
+
+    setSidebarWidth: function(newWidth)
+    {
+        this.sidebarElement.style.width = newWidth + "px";
+        this.contentElement.style.right = newWidth + "px";
+        this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+        this.treeOutline.updateSelection();
+    },
+
+    updateFocusedNode: function(nodeId)
+    {
+        var node = WebInspector.domAgent.nodeForId(nodeId);
+        if (!node)
+            return;
+
+        this.focusedDOMNode = node;
+        this._nodeSearchButton.toggled = false;
+    },
+
+    _setSearchingForNode: function(enabled)
+    {
+        this._nodeSearchButton.toggled = enabled;
+    },
+
+    setSearchingForNode: function(enabled)
+    {
+        InspectorBackend.setSearchingForNode(enabled, this._setSearchingForNode.bind(this));
+    },
+
+    toggleSearchingForNode: function()
+    {
+        this.setSearchingForNode(!this._nodeSearchButton.toggled);
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [ this.contentElement, this.sidebarElement ];
+    }
+}
+
+WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsTreeOutline.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsTreeOutline.js
new file mode 100644
index 0000000..56c3e75
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -0,0 +1,1440 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsTreeOutline = function() {
+    this.element = document.createElement("ol");
+    this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
+    this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
+    this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
+
+    TreeOutline.call(this, this.element);
+
+    this.includeRootDOMNode = true;
+    this.selectEnabled = false;
+    this.showInElementsPanelEnabled = false;
+    this.rootDOMNode = null;
+    this.focusedDOMNode = null;
+
+    this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
+}
+
+WebInspector.ElementsTreeOutline.prototype = {
+    get rootDOMNode()
+    {
+        return this._rootDOMNode;
+    },
+
+    set rootDOMNode(x)
+    {
+        if (this._rootDOMNode === x)
+            return;
+
+        this._rootDOMNode = x;
+
+        this._isXMLMimeType = !!(WebInspector.mainResource && WebInspector.mainResource.mimeType && WebInspector.mainResource.mimeType.match(/x(?:ht)?ml/i));
+
+        this.update();
+    },
+
+    get isXMLMimeType()
+    {
+        return this._isXMLMimeType;
+    },
+
+    nodeNameToCorrectCase: function(nodeName)
+    {
+        return this.isXMLMimeType ? nodeName : nodeName.toLowerCase();
+    },
+
+    get focusedDOMNode()
+    {
+        return this._focusedDOMNode;
+    },
+
+    set focusedDOMNode(x)
+    {
+        if (this._focusedDOMNode === x) {
+            this.revealAndSelectNode(x);
+            return;
+        }
+
+        this._focusedDOMNode = x;
+
+        this.revealAndSelectNode(x);
+
+        // The revealAndSelectNode() method might find a different element if there is inlined text,
+        // and the select() call would change the focusedDOMNode and reenter this setter. So to
+        // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
+        // node as the one passed in.
+        if (this._focusedDOMNode === x)
+            this.focusedNodeChanged();
+    },
+
+    get editing()
+    {
+        return this._editing;
+    },
+
+    update: function()
+    {
+        var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null;
+
+        this.removeChildren();
+
+        if (!this.rootDOMNode)
+            return;
+
+        var treeElement;
+        if (this.includeRootDOMNode) {
+            treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode);
+            treeElement.selectable = this.selectEnabled;
+            this.appendChild(treeElement);
+        } else {
+            // FIXME: this could use findTreeElement to reuse a tree element if it already exists
+            var node = this.rootDOMNode.firstChild;
+            while (node) {
+                treeElement = new WebInspector.ElementsTreeElement(node);
+                treeElement.selectable = this.selectEnabled;
+                this.appendChild(treeElement);
+                node = node.nextSibling;
+            }
+        }
+
+        if (selectedNode)
+            this.revealAndSelectNode(selectedNode);
+    },
+
+    updateSelection: function()
+    {
+        if (!this.selectedTreeElement)
+            return;
+        var element = this.treeOutline.selectedTreeElement;
+        element.updateSelection();
+    },
+
+    focusedNodeChanged: function(forceUpdate) {},
+
+    findTreeElement: function(node)
+    {
+        var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
+        if (!treeElement && node.nodeType === Node.TEXT_NODE) {
+            // The text node might have been inlined if it was short, so try to find the parent element.
+            treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
+        }
+
+        return treeElement;
+    },
+
+    createTreeElementFor: function(node)
+    {
+        var treeElement = this.findTreeElement(node);
+        if (treeElement)
+            return treeElement;
+        if (!node.parentNode)
+            return null;
+
+        var treeElement = this.createTreeElementFor(node.parentNode);
+        if (treeElement && treeElement.showChild(node.index))
+            return treeElement.children[node.index];
+
+        return null;
+    },
+
+    set suppressRevealAndSelect(x)
+    {
+        if (this._suppressRevealAndSelect === x)
+            return;
+        this._suppressRevealAndSelect = x;
+    },
+
+    revealAndSelectNode: function(node)
+    {
+        if (!node || this._suppressRevealAndSelect)
+            return;
+
+        var treeElement = this.createTreeElementFor(node);
+        if (!treeElement)
+            return;
+
+        treeElement.reveal();
+        treeElement.select();
+    },
+
+    _treeElementFromEvent: function(event)
+    {
+        var root = this.element;
+
+        // We choose this X coordinate based on the knowledge that our list
+        // items extend nearly to the right edge of the outer <ol>.
+        var x = root.totalOffsetLeft + root.offsetWidth - 20;
+
+        var y = event.pageY;
+
+        // Our list items have 1-pixel cracks between them vertically. We avoid
+        // the cracks by checking slightly above and slightly below the mouse
+        // and seeing if we hit the same element each time.
+        var elementUnderMouse = this.treeElementFromPoint(x, y);
+        var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
+        var element;
+        if (elementUnderMouse === elementAboveMouse)
+            element = elementUnderMouse;
+        else
+            element = this.treeElementFromPoint(x, y + 2);
+
+        return element;
+    },
+
+    _onmousedown: function(event)
+    {
+        var element = this._treeElementFromEvent(event);
+
+        if (!element || element.isEventWithinDisclosureTriangle(event))
+            return;
+
+        element.select();
+    },
+
+    _onmousemove: function(event)
+    {
+        var element = this._treeElementFromEvent(event);
+        if (element && this._previousHoveredElement === element)
+            return;
+
+        if (this._previousHoveredElement) {
+            this._previousHoveredElement.hovered = false;
+            delete this._previousHoveredElement;
+        }
+
+        if (element) {
+            element.hovered = true;
+            this._previousHoveredElement = element;
+
+            // Lazily compute tag-specific tooltips.
+            if (element.representedObject && !element.tooltip)
+                element._createTooltipForNode();
+        }
+
+        WebInspector.highlightDOMNode(element ? element.representedObject.id : 0);
+    },
+
+    _onmouseout: function(event)
+    {
+        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+        if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element))
+            return;
+
+        if (this._previousHoveredElement) {
+            this._previousHoveredElement.hovered = false;
+            delete this._previousHoveredElement;
+        }
+
+        WebInspector.highlightDOMNode(0);
+    },
+
+    _contextMenuEventFired: function(event)
+    {
+        var listItem = event.target.enclosingNodeOrSelfWithNodeName("LI");
+        if (!listItem || !listItem.treeElement)
+            return;
+
+        var contextMenu = new WebInspector.ContextMenu();
+        if (this.showInElementsPanelEnabled) {
+            function focusElement()
+            {
+                WebInspector.panels.elements.switchToAndFocus(listItem.treeElement.representedObject);
+            }
+            contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this));
+        } else {
+            var href = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
+            var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag");
+            var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
+            var needSeparator;
+            if (href)
+                needSeparator = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
+            if (tag && listItem.treeElement._populateTagContextMenu) {
+                if (needSeparator)
+                    contextMenu.appendSeparator();
+                listItem.treeElement._populateTagContextMenu(contextMenu, event);
+            } else if (textNode && listItem.treeElement._populateTextContextMenu) {
+                if (needSeparator)
+                    contextMenu.appendSeparator();
+                listItem.treeElement._populateTextContextMenu(contextMenu, textNode);
+            }
+        }
+        contextMenu.show(event);
+    }
+}
+
+WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
+
+WebInspector.ElementsTreeElement = function(node, elementCloseTag)
+{
+    this._elementCloseTag = elementCloseTag;
+    var hasChildrenOverride = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node);
+
+    // The title will be updated in onattach.
+    TreeElement.call(this, "", node, hasChildrenOverride);
+
+    if (this.representedObject.nodeType == Node.ELEMENT_NODE && !elementCloseTag)
+        this._canAddAttributes = true;
+    this._searchQuery = null;
+    this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit;
+}
+
+WebInspector.ElementsTreeElement.InitialChildrenLimit = 500;
+
+// A union of HTML4 and HTML5-Draft elements that explicitly
+// or implicitly (for HTML5) forbid the closing tag.
+// FIXME: Revise once HTML5 Final is published.
+WebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [
+    "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame",
+    "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source"
+].keySet();
+
+// These tags we do not allow editing their tag name.
+WebInspector.ElementsTreeElement.EditTagBlacklist = [
+    "html", "head", "body"
+].keySet();
+
+WebInspector.ElementsTreeElement.prototype = {
+    highlightSearchResults: function(searchQuery)
+    {
+        if (this._searchQuery === searchQuery)
+            return;
+
+        this._searchQuery = searchQuery;
+        this.updateTitle();
+    },
+
+    get hovered()
+    {
+        return this._hovered;
+    },
+
+    set hovered(x)
+    {
+        if (this._hovered === x)
+            return;
+
+        this._hovered = x;
+
+        if (this.listItemElement) {
+            if (x) {
+                this.updateSelection();
+                this.listItemElement.addStyleClass("hovered");
+            } else {
+                this.listItemElement.removeStyleClass("hovered");
+            }
+        }
+    },
+
+    get expandedChildrenLimit()
+    {
+        return this._expandedChildrenLimit;
+    },
+
+    set expandedChildrenLimit(x)
+    {
+        if (this._expandedChildrenLimit === x)
+            return;
+
+        this._expandedChildrenLimit = x;
+        if (this.treeOutline && !this._updateChildrenInProgress)
+            this._updateChildren(true);
+    },
+
+    get expandedChildCount()
+    {
+        var count = this.children.length;
+        if (count && this.children[count - 1]._elementCloseTag)
+            count--;
+        if (count && this.children[count - 1].expandAllButton)
+            count--;
+        return count;
+    },
+
+    showChild: function(index)
+    {
+        if (this._elementCloseTag)
+            return;
+
+        if (index >= this.expandedChildrenLimit) {
+            this._expandedChildrenLimit = index + 1;
+            this._updateChildren(true);
+        }
+
+        // Whether index-th child is visible in the children tree
+        return this.expandedChildCount > index;
+    },
+
+    _createTooltipForNode: function()
+    {
+        var node = this.representedObject;
+        if (!node.nodeName || node.nodeName.toLowerCase() !== "img")
+            return;
+
+        function setTooltip(properties)
+        {
+            if (!properties)
+                return;
+
+            if (properties.offsetHeight === properties.naturalHeight && properties.offsetWidth === properties.naturalWidth)
+                this.tooltip = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight);
+            else
+                this.tooltip = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight);
+        }
+        InspectorBackend.getNodeProperties(node.id, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], setTooltip.bind(this));
+    },
+
+    updateSelection: function()
+    {
+        var listItemElement = this.listItemElement;
+        if (!listItemElement)
+            return;
+
+        if (document.body.offsetWidth <= 0) {
+            // The stylesheet hasn't loaded yet or the window is closed,
+            // so we can't calculate what is need. Return early.
+            return;
+        }
+
+        if (!this.selectionElement) {
+            this.selectionElement = document.createElement("div");
+            this.selectionElement.className = "selection selected";
+            listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
+        }
+
+        this.selectionElement.style.height = listItemElement.offsetHeight + "px";
+    },
+
+    onattach: function()
+    {
+        if (this._hovered) {
+            this.updateSelection();
+            this.listItemElement.addStyleClass("hovered");
+        }
+
+        this.updateTitle();
+
+        this._preventFollowingLinksOnDoubleClick();
+    },
+
+    _preventFollowingLinksOnDoubleClick: function()
+    {
+        var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link");
+        if (!links)
+            return;
+
+        for (var i = 0; i < links.length; ++i)
+            links[i].preventFollowOnDoubleClick = true;
+    },
+
+    onpopulate: function()
+    {
+        if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag)
+            return;
+
+        this.updateChildren();
+    },
+
+    updateChildren: function(fullRefresh)
+    {
+        if (this._elementCloseTag)
+            return;
+
+        WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh));
+    },
+
+    insertChildElement: function(child, index, closingTag)
+    {
+        var newElement = new WebInspector.ElementsTreeElement(child, closingTag);
+        newElement.selectable = this.treeOutline.selectEnabled;
+        this.insertChild(newElement, index);
+        return newElement;
+    },
+
+    moveChild: function(child, targetIndex)
+    {
+        var wasSelected = child.selected;
+        this.removeChild(child);
+        this.insertChild(child, targetIndex);
+        if (wasSelected)
+            child.select();
+    },
+
+    _updateChildren: function(fullRefresh)
+    {
+        if (this._updateChildrenInProgress)
+            return;
+
+        this._updateChildrenInProgress = true;
+        var focusedNode = this.treeOutline.focusedDOMNode;
+        var originalScrollTop;
+        if (fullRefresh) {
+            var treeOutlineContainerElement = this.treeOutline.element.parentNode;
+            originalScrollTop = treeOutlineContainerElement.scrollTop;
+            var selectedTreeElement = this.treeOutline.selectedTreeElement;
+            if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
+                this.select();
+            this.removeChildren();
+        }
+
+        var treeElement = this;
+        var treeChildIndex = 0;
+        var elementToSelect;
+
+        function updateChildrenOfNode(node)
+        {
+            var treeOutline = treeElement.treeOutline;
+            var child = node.firstChild;
+            while (child) {
+                var currentTreeElement = treeElement.children[treeChildIndex];
+                if (!currentTreeElement || currentTreeElement.representedObject !== child) {
+                    // Find any existing element that is later in the children list.
+                    var existingTreeElement = null;
+                    for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) {
+                        if (treeElement.children[i].representedObject === child) {
+                            existingTreeElement = treeElement.children[i];
+                            break;
+                        }
+                    }
+
+                    if (existingTreeElement && existingTreeElement.parent === treeElement) {
+                        // If an existing element was found and it has the same parent, just move it.
+                        treeElement.moveChild(existingTreeElement, treeChildIndex);
+                    } else {
+                        // No existing element found, insert a new element.
+                        if (treeChildIndex < treeElement.expandedChildrenLimit) {
+                            var newElement = treeElement.insertChildElement(child, treeChildIndex);
+                            if (child === focusedNode)
+                                elementToSelect = newElement;
+                            if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit)
+                                treeElement.expandedChildrenLimit++;
+                        }
+                    }
+                }
+
+                child = child.nextSibling;
+                ++treeChildIndex;
+            }
+        }
+
+        // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
+        for (var i = (this.children.length - 1); i >= 0; --i) {
+            var currentChild = this.children[i];
+            var currentNode = currentChild.representedObject;
+            var currentParentNode = currentNode.parentNode;
+
+            if (currentParentNode === this.representedObject)
+                continue;
+
+            var selectedTreeElement = this.treeOutline.selectedTreeElement;
+            if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
+                this.select();
+
+            this.removeChildAtIndex(i);
+        }
+
+        updateChildrenOfNode(this.representedObject);
+        this.adjustCollapsedRange(false);
+
+        var lastChild = this.children[this.children.length - 1];
+        if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
+            this.insertChildElement(this.representedObject, this.children.length, true);
+
+        // We want to restore the original selection and tree scroll position after a full refresh, if possible.
+        if (fullRefresh && elementToSelect) {
+            elementToSelect.select();
+            if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight)
+                treeOutlineContainerElement.scrollTop = originalScrollTop;
+        }
+
+        delete this._updateChildrenInProgress;
+    },
+
+    adjustCollapsedRange: function()
+    {
+        // Ensure precondition: only the tree elements for node children are found in the tree
+        // (not the Expand All button or the closing tag).
+        if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent)
+            this.removeChild(this.expandAllButtonElement.__treeElement);
+
+        const node = this.representedObject;
+        if (!node.children)
+            return;
+        const childNodeCount = node.children.length;
+
+        // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom.
+        for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i)
+            this.insertChildElement(node.children[i], i);
+
+        const expandedChildCount = this.expandedChildCount;
+        if (childNodeCount > this.expandedChildCount) {
+            var targetButtonIndex = expandedChildCount;
+            if (!this.expandAllButtonElement) {
+                var item = new TreeElement(null, null, false);
+                item.titleHTML = "<button class=\"show-all-nodes\" value=\"\" />";
+                item.selectable = false;
+                item.expandAllButton = true;
+                this.insertChild(item, targetButtonIndex);
+                this.expandAllButtonElement = item.listItemElement.firstChild;
+                this.expandAllButtonElement.__treeElement = item;
+                this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false);
+            } else if (!this.expandAllButtonElement.__treeElement.parent)
+                this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex);
+            this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount);
+        } else if (this.expandAllButtonElement)
+            delete this.expandAllButtonElement;
+    },
+
+    handleLoadAllChildren: function()
+    {
+        this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit);
+    },
+
+    onexpand: function()
+    {
+        if (this._elementCloseTag)
+            return;
+
+        this.updateTitle();
+        this.treeOutline.updateSelection();
+    },
+
+    oncollapse: function()
+    {
+        if (this._elementCloseTag)
+            return;
+
+        this.updateTitle();
+        this.treeOutline.updateSelection();
+    },
+
+    onreveal: function()
+    {
+        if (this.listItemElement)
+            this.listItemElement.scrollIntoViewIfNeeded(false);
+    },
+
+    onselect: function(treeElement, selectedByUser)
+    {
+        this.treeOutline.suppressRevealAndSelect = true;
+        this.treeOutline.focusedDOMNode = this.representedObject;
+        if (selectedByUser)
+            WebInspector.highlightDOMNode(this.representedObject.id);
+        this.updateSelection();
+        this.treeOutline.suppressRevealAndSelect = false;
+    },
+
+    ondelete: function()
+    {
+        var startTagTreeElement = this.treeOutline.findTreeElement(this.representedObject);
+        startTagTreeElement ? startTagTreeElement.remove() : this.remove();
+        return true;
+    },
+
+    onenter: function()
+    {
+        // On Enter or Return start editing the first attribute
+        // or create a new attribute on the selected element.
+        if (this.treeOutline.editing)
+            return false;
+
+        this._startEditing();
+
+        // prevent a newline from being immediately inserted
+        return true;
+    },
+
+    selectOnMouseDown: function(event)
+    {
+        TreeElement.prototype.selectOnMouseDown.call(this, event);
+
+        if (this._editing)
+            return;
+
+        if (this.treeOutline.showInElementsPanelEnabled) {
+            WebInspector.showPanel("elements");
+            WebInspector.panels.elements.focusedDOMNode = this.representedObject;
+        }
+
+        // Prevent selecting the nearest word on double click.
+        if (event.detail >= 2)
+            event.preventDefault();
+    },
+
+    ondblclick: function(event)
+    {
+        if (this._editing || this._elementCloseTag)
+            return;
+
+        if (this._startEditingTarget(event.target))
+            return;
+
+        if (this.hasChildren && !this.expanded)
+            this.expand();
+    },
+
+    _insertInLastAttributePosition: function(tag, node)
+    {
+        if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
+            tag.insertBefore(node, tag.lastChild);
+        else {
+            var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
+            tag.textContent = '';
+            tag.appendChild(document.createTextNode('<'+nodeName));
+            tag.appendChild(node);
+            tag.appendChild(document.createTextNode('>'));
+        }
+
+        this.updateSelection();
+    },
+
+    _startEditingTarget: function(eventTarget)
+    {
+        if (this.treeOutline.focusedDOMNode != this.representedObject)
+            return;
+
+        if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.representedObject.nodeType != Node.TEXT_NODE)
+            return false;
+
+        var textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node");
+        if (textNode)
+            return this._startEditingTextNode(textNode);
+
+        var attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute");
+        if (attribute)
+            return this._startEditingAttribute(attribute, eventTarget);
+
+        var tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name");
+        if (tagName)
+            return this._startEditingTagName(tagName);
+
+        var newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute");
+        if (newAttribute)
+            return this._addNewAttribute();
+
+        return false;
+    },
+
+    _populateTagContextMenu: function(contextMenu, event)
+    {
+        var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
+        var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");
+
+        // Add attribute-related actions.
+        contextMenu.appendItem(WebInspector.UIString("Add Attribute"), this._addNewAttribute.bind(this));
+        if (attribute && !newAttribute)
+            contextMenu.appendItem(WebInspector.UIString("Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target));
+        contextMenu.appendSeparator();
+
+        // Add free-form node-related actions.
+        contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), this._editAsHTML.bind(this));
+        contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this));
+        contextMenu.appendItem(WebInspector.UIString("Delete Node"), this.remove.bind(this));
+
+        if (Preferences.nativeInstrumentationEnabled) {
+            // Add debbuging-related actions
+            contextMenu.appendSeparator();
+
+            function handlerFunction(nodeId, breakType)
+            {
+                WebInspector.breakpointManager.createDOMBreakpoint(nodeId, breakType);
+                WebInspector.panels.elements.sidebarPanes.domBreakpoints.expand();
+            }
+            var node = this.representedObject;
+            for (var key in WebInspector.DOMBreakpointTypes) {
+                var type = WebInspector.DOMBreakpointTypes[key];
+                var label = WebInspector.domBreakpointTypeContextMenuLabel(type);
+                var breakpoint = node.breakpoints[type];
+                if (!breakpoint)
+                    var handler = handlerFunction.bind(this, node.id, type);
+                else
+                    var handler = breakpoint.remove.bind(breakpoint);
+                contextMenu.appendCheckboxItem(label, handler, !!breakpoint);
+            }
+        }
+    },
+
+    _populateTextContextMenu: function(contextMenu, textNode)
+    {
+        contextMenu.appendItem(WebInspector.UIString("Edit Text"), this._startEditingTextNode.bind(this, textNode));
+    },
+
+    _startEditing: function()
+    {
+        if (this.treeOutline.focusedDOMNode !== this.representedObject)
+            return;
+
+        var listItem = this._listItemNode;
+
+        if (this._canAddAttributes) {
+            var attribute = listItem.getElementsByClassName("webkit-html-attribute")[0];
+            if (attribute)
+                return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]);
+
+            return this._addNewAttribute();
+        }
+
+        if (this.representedObject.nodeType === Node.TEXT_NODE) {
+            var textNode = listItem.getElementsByClassName("webkit-html-text-node")[0];
+            if (textNode)
+                return this._startEditingTextNode(textNode);
+            return;
+        }
+    },
+
+    _addNewAttribute: function()
+    {
+        // Cannot just convert the textual html into an element without
+        // a parent node. Use a temporary span container for the HTML.
+        var container = document.createElement("span");
+        container.innerHTML = this._attributeHTML(" ", "");
+        var attr = container.firstChild;
+        attr.style.marginLeft = "2px"; // overrides the .editing margin rule
+        attr.style.marginRight = "2px"; // overrides the .editing margin rule
+
+        var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
+        this._insertInLastAttributePosition(tag, attr);
+        return this._startEditingAttribute(attr, attr);
+    },
+
+    _triggerEditAttribute: function(attributeName)
+    {
+        var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
+        for (var i = 0, len = attributeElements.length; i < len; ++i) {
+            if (attributeElements[i].textContent === attributeName) {
+                for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
+                    if (elem.nodeType !== Node.ELEMENT_NODE)
+                        continue;
+
+                    if (elem.hasStyleClass("webkit-html-attribute-value"))
+                        return this._startEditingAttribute(elem.parentNode, elem);
+                }
+            }
+        }
+    },
+
+    _startEditingAttribute: function(attribute, elementForSelection)
+    {
+        if (WebInspector.isBeingEdited(attribute))
+            return true;
+
+        var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
+        if (!attributeNameElement)
+            return false;
+
+        var attributeName = attributeNameElement.innerText;
+
+        function removeZeroWidthSpaceRecursive(node)
+        {
+            if (node.nodeType === Node.TEXT_NODE) {
+                node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
+                return;
+            }
+
+            if (node.nodeType !== Node.ELEMENT_NODE)
+                return;
+
+            for (var child = node.firstChild; child; child = child.nextSibling)
+                removeZeroWidthSpaceRecursive(child);
+        }
+
+        // Remove zero-width spaces that were added by nodeTitleInfo.
+        removeZeroWidthSpaceRecursive(attribute);
+
+        this._editing = WebInspector.startEditing(attribute, {
+            context: attributeName,
+            commitHandler: this._attributeEditingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
+
+        return true;
+    },
+
+    _startEditingTextNode: function(textNode)
+    {
+        if (WebInspector.isBeingEdited(textNode))
+            return true;
+
+        this._editing = WebInspector.startEditing(textNode, {
+            context: null,
+            commitHandler: this._textNodeEditingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
+
+        return true;
+    },
+
+    _startEditingTagName: function(tagNameElement)
+    {
+        if (!tagNameElement) {
+            tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0];
+            if (!tagNameElement)
+                return false;
+        }
+
+        var tagName = tagNameElement.textContent;
+        if (WebInspector.ElementsTreeElement.EditTagBlacklist[tagName.toLowerCase()])
+            return false;
+
+        if (WebInspector.isBeingEdited(tagNameElement))
+            return true;
+
+        var closingTagElement = this._distinctClosingTagElement();
+
+        function keyupListener(event)
+        {
+            if (closingTagElement)
+                closingTagElement.textContent = "</" + tagNameElement.textContent + ">";
+        }
+
+        function editingComitted(element, newTagName)
+        {
+            tagNameElement.removeEventListener('keyup', keyupListener, false);
+            this._tagNameEditingCommitted.apply(this, arguments);
+        }
+
+        function editingCancelled()
+        {
+            tagNameElement.removeEventListener('keyup', keyupListener, false);
+            this._editingCancelled.apply(this, arguments);
+        }
+
+        tagNameElement.addEventListener('keyup', keyupListener, false);
+
+        this._editing = WebInspector.startEditing(tagNameElement, {
+            context: tagName,
+            commitHandler: editingComitted.bind(this),
+            cancelHandler: editingCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
+        return true;
+    },
+
+    _startEditingAsHTML: function(commitCallback, initialValue)
+    {
+        if (this._htmlEditElement && WebInspector.isBeingEdited(this._htmlEditElement))
+            return true;
+
+        this._htmlEditElement = document.createElement("div");
+        this._htmlEditElement.className = "source-code elements-tree-editor";
+        this._htmlEditElement.textContent = initialValue;
+
+        // Hide header items.
+        var child = this.listItemElement.firstChild;
+        while (child) {
+            child.style.display = "none";
+            child = child.nextSibling;
+        }
+        // Hide children item.
+        if (this._childrenListNode)
+            this._childrenListNode.style.display = "none";
+        // Append editor.
+        this.listItemElement.appendChild(this._htmlEditElement);
+
+        this.updateSelection();
+
+        function commit()
+        {
+            commitCallback(this._htmlEditElement.textContent);
+            dispose.call(this);
+        }
+
+        function dispose()
+        {
+            delete this._editing;
+
+            // Remove editor.
+            this.listItemElement.removeChild(this._htmlEditElement);
+            delete this._htmlEditElement;
+            // Unhide children item.
+            if (this._childrenListNode)
+                this._childrenListNode.style.removeProperty("display");
+            // Unhide header items.
+            var child = this.listItemElement.firstChild;
+            while (child) {
+                child.style.removeProperty("display");
+                child = child.nextSibling;
+            }
+
+            this.updateSelection();
+        }
+
+        this._editing = WebInspector.startEditing(this._htmlEditElement, {
+            context: null,
+            commitHandler: commit.bind(this),
+            cancelHandler: dispose.bind(this),
+            multiline: true
+        });
+    },
+
+    _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
+    {
+        delete this._editing;
+
+        // Before we do anything, determine where we should move
+        // next based on the current element's settings
+        var moveToAttribute, moveToTagName, moveToNewAttribute;
+        if (moveDirection) {
+            var found = false;
+
+            // Search for the attribute's position, and then decide where to move to.
+            var attributes = this.representedObject.attributes;
+            for (var i = 0; i < attributes.length; ++i) {
+                if (attributes[i].name === attributeName) {
+                    found = true;
+                    if (moveDirection === "backward") {
+                        if (i === 0)
+                            moveToTagName = true;
+                        else
+                            moveToAttribute = attributes[i - 1].name;
+                    } else if (moveDirection === "forward") {
+                        if (i === attributes.length - 1)
+                            moveToNewAttribute = true;
+                        else
+                            moveToAttribute = attributes[i + 1].name;
+                    }
+                }
+            }
+
+            // Moving From the "New Attribute" position.
+            if (!found) {
+                if (moveDirection === "backward" && attributes.length > 0)
+                    moveToAttribute = attributes[attributes.length - 1].name;
+                else if (moveDirection === "forward") {
+                    if (!/^\s*$/.test(newText))
+                        moveToNewAttribute = true;
+                    else
+                        moveToTagName = true;
+                }
+            }
+        }
+
+        function moveToNextAttributeIfNeeded()
+        {
+            // Cleanup empty new attribute sections.
+            if (element.textContent.trim().length === 0)
+                element.parentNode.removeChild(element);
+
+            // Make the move.
+            if (moveToAttribute)
+                this._triggerEditAttribute(moveToAttribute);
+            else if (moveToNewAttribute)
+                this._addNewAttribute();
+            else if (moveToTagName)
+                this._startEditingTagName();
+        }
+
+        function regenerateStyledAttribute(name, value)
+        {
+            var previous = element.previousSibling;
+            if (!previous || previous.nodeType !== Node.TEXT_NODE)
+                element.parentNode.insertBefore(document.createTextNode(" "), element);
+            element.outerHTML = this._attributeHTML(name, value);
+        }
+
+        var parseContainerElement = document.createElement("span");
+        parseContainerElement.innerHTML = "<span " + newText + "></span>";
+        var parseElement = parseContainerElement.firstChild;
+
+        if (!parseElement) {
+            this._editingCancelled(element, attributeName);
+            moveToNextAttributeIfNeeded.call(this);
+            return;
+        }
+
+        if (!parseElement.hasAttributes()) {
+            this.representedObject.removeAttribute(attributeName);
+            this.treeOutline.focusedNodeChanged(true);
+            moveToNextAttributeIfNeeded.call(this);
+            return;
+        }
+
+        var foundOriginalAttribute = false;
+        for (var i = 0; i < parseElement.attributes.length; ++i) {
+            var attr = parseElement.attributes[i];
+            foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
+            try {
+                this.representedObject.setAttribute(attr.name, attr.value);
+                regenerateStyledAttribute.call(this, attr.name, attr.value);
+            } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
+        }
+
+        if (!foundOriginalAttribute)
+            this.representedObject.removeAttribute(attributeName);
+
+        this.treeOutline.focusedNodeChanged(true);
+
+        moveToNextAttributeIfNeeded.call(this);
+    },
+
+    _tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection)
+    {
+        delete this._editing;
+        var self = this;
+
+        function cancel()
+        {
+            var closingTagElement = self._distinctClosingTagElement();
+            if (closingTagElement)
+                closingTagElement.textContent = "</" + tagName + ">";
+
+            self._editingCancelled(element, tagName);
+            moveToNextAttributeIfNeeded.call(self);
+        }
+
+        function moveToNextAttributeIfNeeded()
+        {
+            if (moveDirection !== "forward") {
+                this._addNewAttribute();
+                return;
+            }
+
+            var attributes = this.representedObject.attributes;
+            if (attributes.length > 0)
+                this._triggerEditAttribute(attributes[0].name);
+            else
+                this._addNewAttribute();
+        }
+
+        newText = newText.trim();
+        if (newText === oldText) {
+            cancel();
+            return;
+        }
+
+        var treeOutline = this.treeOutline;
+        var wasExpanded = this.expanded;
+
+        function changeTagNameCallback(nodeId)
+        {
+            if (!nodeId) {
+                cancel();
+                return;
+            }
+
+            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
+            WebInspector.panels.elements.updateModifiedNodes();
+
+            WebInspector.updateFocusedNode(nodeId);
+            var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
+            if (wasExpanded)
+                newTreeItem.expand();
+
+            moveToNextAttributeIfNeeded.call(newTreeItem);
+        }
+
+        InspectorBackend.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
+    },
+
+    _textNodeEditingCommitted: function(element, newText)
+    {
+        delete this._editing;
+
+        var textNode;
+        if (this.representedObject.nodeType === Node.ELEMENT_NODE) {
+            // We only show text nodes inline in elements if the element only
+            // has a single child, and that child is a text node.
+            textNode = this.representedObject.firstChild;
+        } else if (this.representedObject.nodeType == Node.TEXT_NODE)
+            textNode = this.representedObject;
+
+        textNode.nodeValue = newText;
+    },
+
+    _editingCancelled: function(element, context)
+    {
+        delete this._editing;
+
+        // Need to restore attributes structure.
+        this.updateTitle();
+    },
+
+    _distinctClosingTagElement: function()
+    {
+        // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM
+
+        // For an expanded element, it will be the last element with class "close"
+        // in the child element list.
+        if (this.expanded) {
+            var closers = this._childrenListNode.querySelectorAll(".close");
+            return closers[closers.length-1];
+        }
+
+        // Remaining cases are single line non-expanded elements with a closing
+        // tag, or HTML elements without a closing tag (such as <br>). Return
+        // null in the case where there isn't a closing tag.
+        var tags = this.listItemElement.getElementsByClassName("webkit-html-tag");
+        return (tags.length === 1 ? null : tags[tags.length-1]);
+    },
+
+    updateTitle: function()
+    {
+        // If we are editing, return early to prevent canceling the edit.
+        // After editing is committed updateTitle will be called.
+        if (this._editing)
+            return;
+
+        this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
+        delete this.selectionElement;
+        this.updateSelection();
+        this._preventFollowingLinksOnDoubleClick();
+        this._highlightSearchResults();
+    },
+
+    _attributeHTML: function(name, value, node, linkify)
+    {
+        var hasText = (value.length > 0);
+        var html = "<span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + name.escapeHTML() + "</span>";
+
+        if (hasText)
+            html += "=&#8203;\"";
+
+        if (linkify && (name === "src" || name === "href")) {
+            var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value);
+            value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
+            html += linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName.toLowerCase() === "a");
+        } else {
+            value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1&#8203;");
+            html += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
+        }
+
+        if (hasText)
+            html += "\"";
+
+        html += "</span>";
+        return html;
+    },
+
+    _tagHTML: function(tagName, isClosingTag, isDistinctTreeElement, linkify)
+    {
+        var node = this.representedObject;
+        var result = "<span class=\"webkit-html-tag" + (isClosingTag && isDistinctTreeElement ? " close" : "")  + "\">&lt;";
+        result += "<span " + (isClosingTag ? "" : "class=\"webkit-html-tag-name\"") + ">" + (isClosingTag ? "/" : "") + tagName + "</span>";
+        if (!isClosingTag && node.hasAttributes()) {
+            for (var i = 0; i < node.attributes.length; ++i) {
+                var attr = node.attributes[i];
+                result += " " + this._attributeHTML(attr.name, attr.value, node, linkify);
+            }
+        }
+        result += "&gt;</span>&#8203;";
+
+        return result;
+    },
+
+    _nodeTitleInfo: function(linkify)
+    {
+        var node = this.representedObject;
+        var info = {titleHTML: "", hasChildren: this.hasChildren};
+
+        switch (node.nodeType) {
+            case Node.DOCUMENT_NODE:
+                info.titleHTML = "Document";
+                break;
+
+            case Node.DOCUMENT_FRAGMENT_NODE:
+                info.titleHTML = "Document Fragment";
+                break;
+
+            case Node.ATTRIBUTE_NODE:
+                var value = node.value || "\u200B"; // Zero width space to force showing an empty value.
+                info.titleHTML = this._attributeHTML(node.name, value);
+                break;
+
+            case Node.ELEMENT_NODE:
+                var tagName = this.treeOutline.nodeNameToCorrectCase(node.nodeName).escapeHTML();
+                if (this._elementCloseTag) {
+                    info.titleHTML = this._tagHTML(tagName, true, true);
+                    info.hasChildren = false;
+                    break;
+                }
+
+                var titleHTML = this._tagHTML(tagName, false, false, linkify);
+
+                var textChild = onlyTextChild.call(node);
+                var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength;
+
+                if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) {
+                    if (this.hasChildren)
+                        titleHTML += "<span class=\"webkit-html-text-node\">&#8230;</span>&#8203;";
+                    titleHTML += this._tagHTML(tagName, true, false);
+                }
+
+                // If this element only has a single child that is a text node,
+                // just show that text and the closing tag inline rather than
+                // create a subtree for them
+                if (showInlineText) {
+                    titleHTML += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>&#8203;" + this._tagHTML(tagName, true, false);
+                    info.hasChildren = false;
+                }
+                info.titleHTML = titleHTML;
+                break;
+
+            case Node.TEXT_NODE:
+                if (isNodeWhitespace.call(node))
+                    info.titleHTML = "(whitespace)";
+                else {
+                    if (node.parentNode && node.parentNode.nodeName.toLowerCase() === "script") {
+                        var newNode = document.createElement("span");
+                        newNode.textContent = node.textContent;
+
+                        var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript");
+                        javascriptSyntaxHighlighter.syntaxHighlightNode(newNode);
+
+                        info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-js-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
+                    } else if (node.parentNode && node.parentNode.nodeName.toLowerCase() === "style") {
+                        var newNode = document.createElement("span");
+                        newNode.textContent = node.textContent;
+
+                        var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css");
+                        cssSyntaxHighlighter.syntaxHighlightNode(newNode);
+
+                        info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-css-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
+                    } else
+                        info.titleHTML = "\"<span class=\"webkit-html-text-node\">" + node.nodeValue.escapeHTML() + "</span>\"";
+                }
+                break;
+
+            case Node.COMMENT_NODE:
+                info.titleHTML = "<span class=\"webkit-html-comment\">&lt;!--" + node.nodeValue.escapeHTML() + "--&gt;</span>";
+                break;
+
+            case Node.DOCUMENT_TYPE_NODE:
+                var titleHTML = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + node.nodeName;
+                if (node.publicId) {
+                    titleHTML += " PUBLIC \"" + node.publicId + "\"";
+                    if (node.systemId)
+                        titleHTML += " \"" + node.systemId + "\"";
+                } else if (node.systemId)
+                    titleHTML += " SYSTEM \"" + node.systemId + "\"";
+                if (node.internalSubset)
+                    titleHTML += " [" + node.internalSubset + "]";
+                titleHTML += "&gt;</span>";
+                info.titleHTML = titleHTML;
+                break;
+
+            case Node.CDATA_SECTION_NODE:
+                info.titleHTML = "<span class=\"webkit-html-text-node\">&lt;![CDATA[" + node.nodeValue.escapeHTML() + "]]&gt;</span>";
+                break;
+            default:
+                info.titleHTML = this.treeOutline.nodeNameToCorrectCase(node.nodeName).collapseWhitespace().escapeHTML();
+        }
+
+        return info;
+    },
+
+    _showInlineText: function(node)
+    {
+        if (node.nodeType === Node.ELEMENT_NODE) {
+            var textChild = onlyTextChild.call(node);
+            if (textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength)
+                return true;
+        }
+        return false;
+    },
+
+    remove: function()
+    {
+        var parentElement = this.parent;
+        if (!parentElement)
+            return;
+
+        var self = this;
+        function removeNodeCallback(removedNodeId)
+        {
+            // -1 is an error code, which means removing the node from the DOM failed,
+            // so we shouldn't remove it from the tree.
+            if (removedNodeId === -1)
+                return;
+
+            parentElement.removeChild(self);
+            parentElement.adjustCollapsedRange(true);
+        }
+
+        InspectorBackend.removeNode(this.representedObject.id, removeNodeCallback);
+    },
+
+    _editAsHTML: function()
+    {
+        var treeOutline = this.treeOutline;
+        var node = this.representedObject;
+        var wasExpanded = this.expanded;
+
+        function selectNode(nodeId)
+        {
+            if (!nodeId)
+                return;
+
+            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
+            WebInspector.panels.elements.updateModifiedNodes();
+
+            WebInspector.updateFocusedNode(nodeId);
+            if (wasExpanded) {
+                var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
+                if (newTreeItem)
+                    newTreeItem.expand();
+            }
+        }
+
+        function commitChange(value)
+        {
+            InspectorBackend.setOuterHTML(node.id, value, selectNode);
+        }
+
+        InspectorBackend.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
+    },
+
+    _copyHTML: function()
+    {
+        InspectorBackend.copyNode(this.representedObject.id);
+    },
+
+    _highlightSearchResults: function()
+    {
+        if (!this._searchQuery)
+            return;
+        var text = this.listItemElement.textContent;
+        var regexObject = createSearchRegex(this._searchQuery);
+
+        var offset = 0;
+        var match = regexObject.exec(text);
+        while (match) {
+            highlightSearchResult(this.listItemElement, offset + match.index, match[0].length);
+            offset += match.index + 1;
+            text = text.substring(match.index + 1);
+            match = regexObject.exec(text);
+        }
+    }
+}
+
+WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/EventListenersSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/EventListenersSidebarPane.js
new file mode 100644
index 0000000..bc8bb12
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/EventListenersSidebarPane.js
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.EventListenersSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners"));
+    this.bodyElement.addStyleClass("events-pane");
+
+    this.sections = [];
+
+    this.settingsSelectElement = document.createElement("select");
+
+    var option = document.createElement("option");
+    option.value = "all";
+    option.label = WebInspector.UIString("All Nodes");
+    this.settingsSelectElement.appendChild(option);
+
+    option = document.createElement("option");
+    option.value = "selected";
+    option.label = WebInspector.UIString("Selected Node Only");
+    this.settingsSelectElement.appendChild(option);
+
+    var filter = WebInspector.settings.eventListenersFilter;
+    if (filter === "all")
+        this.settingsSelectElement[0].selected = true;
+    else if (filter === "selected")
+        this.settingsSelectElement[1].selected = true;
+    this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
+    this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
+
+    this.titleElement.appendChild(this.settingsSelectElement);
+}
+
+WebInspector.EventListenersSidebarPane.prototype = {
+    update: function(node)
+    {
+        var body = this.bodyElement;
+        body.removeChildren();
+        this.sections = [];
+
+        var self = this;
+        function callback(nodeId, eventListeners) {
+            var sectionNames = [];
+            var sectionMap = {};
+            for (var i = 0; i < eventListeners.length; ++i) {
+                var eventListener = eventListeners[i];
+                eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId);
+                delete eventListener.nodeId; // no longer needed
+                if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listenerBody.toString()))
+                    continue; // ignore event listeners generated by monitorEvent
+                var type = eventListener.type;
+                var section = sectionMap[type];
+                if (!section) {
+                    section = new WebInspector.EventListenersSection(type, nodeId);
+                    sectionMap[type] = section;
+                    sectionNames.push(type);
+                    self.sections.push(section);
+                }
+                section.addListener(eventListener);
+            }
+            
+            if (sectionNames.length === 0) {
+                var div = document.createElement("div");
+                div.className = "info";
+                div.textContent = WebInspector.UIString("No Event Listeners");
+                body.appendChild(div);
+                return;
+            }
+
+            sectionNames.sort();
+            for (var i = 0; i < sectionNames.length; ++i) {
+                var section = sectionMap[sectionNames[i]];
+                section.update();
+                body.appendChild(section.element);
+            }
+        }
+
+        WebInspector.EventListeners.getEventListenersForNodeAsync(node, callback);
+    },
+
+    _changeSetting: function(event)
+    {
+        var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
+        WebInspector.settings.eventListenersFilter = selectedOption.value;
+
+        for (var i = 0; i < this.sections.length; ++i)
+            this.sections[i].update();
+    }
+}
+
+WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.EventListenersSection = function(title, nodeId)
+{
+    this.eventListeners = [];
+    this._nodeId = nodeId;
+    WebInspector.PropertiesSection.call(this, title);
+
+    // Changed from a Properties List
+    this.propertiesElement.parentNode.removeChild(this.propertiesElement);
+    delete this.propertiesElement;
+    delete this.propertiesTreeOutline;
+
+    this.eventBars = document.createElement("div");
+    this.eventBars.className = "event-bars";
+    this.element.appendChild(this.eventBars);
+}
+
+WebInspector.EventListenersSection.prototype = {
+    update: function()
+    {
+        // A Filtered Array simplifies when to create connectors
+        var filteredEventListeners = this.eventListeners;
+        if (WebInspector.settings.eventListenersFilter === "selected") {
+            filteredEventListeners = [];
+            for (var i = 0; i < this.eventListeners.length; ++i) {
+                var eventListener = this.eventListeners[i];
+                if (eventListener.node.id === this._nodeId)
+                    filteredEventListeners.push(eventListener);
+            }
+        }
+
+        this.eventBars.removeChildren();
+        var length = filteredEventListeners.length;
+        for (var i = 0; i < length; ++i) {
+            var eventListener = filteredEventListeners[i];
+            var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId);
+            this.eventBars.appendChild(eventListenerBar.element);
+        }
+    },
+
+    addListener: function(eventListener)
+    {
+        this.eventListeners.push(eventListener);
+    }
+}
+
+WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.EventListenerBar = function(eventListener, nodeId)
+{
+    this.eventListener = eventListener;
+    this._nodeId = nodeId;
+    WebInspector.ObjectPropertiesSection.call(this);
+    this._setNodeTitle();
+    this._setFunctionSubtitle();
+    this.editable = false;
+    this.element.className = "event-bar"; /* Changed from "section" */
+    this.headerElement.addStyleClass("source-code");
+    this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */
+}
+
+WebInspector.EventListenerBar.prototype = {
+    update: function()
+    {
+        function updateWithNodeObject(nodeObject)
+        {
+            var properties = [];
+            if (nodeObject)
+                properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));
+
+            for (var propertyName in this.eventListener) {
+                var value = WebInspector.RemoteObject.fromPrimitiveValue(this.eventListener[propertyName]);
+                properties.push(new WebInspector.RemoteObjectProperty(propertyName, value));
+            }
+            this.updateProperties(properties);
+        }
+        var node = this.eventListener.node;
+        delete this.eventListener.node;
+        WebInspector.RemoteObject.resolveNode(node, updateWithNodeObject.bind(this));
+    },
+
+    _setNodeTitle: function()
+    {
+        var node = this.eventListener.node;
+        if (!node)
+            return;
+
+        if (node.nodeType === Node.DOCUMENT_NODE) {
+            this.titleElement.textContent = "document";
+            return;
+        }
+
+        if (node.id === this._nodeId) {
+            this.titleElement.textContent = appropriateSelectorForNode(node);
+            return;
+        }
+
+        this.titleElement.removeChildren();
+        this.titleElement.appendChild(WebInspector.panels.elements.linkifyNodeReference(this.eventListener.node));
+    },
+
+    _setFunctionSubtitle: function()
+    {
+        // Requires that Function.toString() return at least the function's signature.
+        if (this.eventListener.sourceName) {
+            this.subtitleElement.removeChildren();
+            this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(this.eventListener.sourceName, "scripts", this.eventListener.lineNumber));
+        } else {
+            var match = this.eventListener.listenerBody.match(/function ([^\(]+?)\(/);
+            if (match)
+                this.subtitleElement.textContent = match[1];
+            else
+                this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)");
+        }
+    }
+}
+
+WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPI.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPI.js
new file mode 100644
index 0000000..6a11d62
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPI.js
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
+{
+
+// Here and below, all constructors are private to API implementation.
+// For a public type Foo, if internal fields are present, these are on
+// a private FooImpl type, an instance of FooImpl is used in a closure
+// by Foo consutrctor to re-bind publicly exported members to an instance
+// of Foo.
+
+function EventSinkImpl(type, customDispatch)
+{
+    this._type = type;
+    this._listeners = [];
+    this._customDispatch = customDispatch;
+}
+
+EventSinkImpl.prototype = {
+    addListener: function(callback)
+    {
+        if (typeof callback != "function")
+            throw new "addListener: callback is not a function";
+        if (this._listeners.length === 0)
+            extensionServer.sendRequest({ command: "subscribe", type: this._type });
+        this._listeners.push(callback);
+        extensionServer.registerHandler("notify-" + this._type, bind(this._dispatch, this));
+    },
+
+    removeListener: function(callback)
+    {
+        var listeners = this._listeners;
+
+        for (var i = 0; i < listeners.length; ++i) {
+            if (listeners[i] === callback) {
+                listeners.splice(i, 1);
+                break;
+            }
+        }
+        if (this._listeners.length === 0)
+            extensionServer.sendRequest({ command: "unsubscribe", type: this._type });
+    },
+
+    _fire: function()
+    {
+        var listeners = this._listeners.slice();
+        for (var i = 0; i < listeners.length; ++i)
+            listeners[i].apply(null, arguments);
+    },
+
+    _dispatch: function(request)
+    {
+         if (this._customDispatch)
+             this._customDispatch.call(this, request);
+         else
+             this._fire.apply(this, request.arguments);
+    }
+}
+
+function InspectorExtensionAPI()
+{
+    this.audits = new Audits();
+    this.inspectedWindow = new InspectedWindow();
+    this.panels = new Panels();
+    this.resources = new Resources();
+
+    this.onReset = new EventSink("reset");
+}
+
+InspectorExtensionAPI.prototype = {
+    log: function(message)
+    {
+        extensionServer.sendRequest({ command: "log", message: message });
+    }
+}
+
+function Resources()
+{
+    function resourceDispatch(request)
+    {
+        var resource = request.arguments[1];
+        resource.__proto__ = new Resource(request.arguments[0]);
+        this._fire(resource);
+    }
+    this.onFinished = new EventSink("resource-finished", resourceDispatch);
+}
+
+Resources.prototype = {
+    getHAR: function(callback)
+    {
+        function callbackWrapper(result)
+        {
+            var entries = (result && result.entries) || [];
+            for (var i = 0; i < entries.length; ++i) {
+                entries[i].__proto__ = new Resource(entries[i]._resourceId);
+                delete entries[i]._resourceId;
+            }
+            callback(result);
+        }
+        return extensionServer.sendRequest({ command: "getHAR" }, callback && callbackWrapper);
+    },
+
+    addRequestHeaders: function(headers)
+    {
+        return extensionServer.sendRequest({ command: "addRequestHeaders", headers: headers, extensionId: location.hostname });
+    }
+}
+
+function ResourceImpl(id)
+{
+    this._id = id;
+}
+
+ResourceImpl.prototype = {
+    getContent: function(callback)
+    {
+        function callbackWrapper(response)
+        {
+            callback(response.content, response.encoding);
+        }
+        extensionServer.sendRequest({ command: "getResourceContent", id: this._id }, callback && callbackWrapper);
+    }
+};
+
+function Panels()
+{
+    var panels = {
+        elements: new ElementsPanel()
+    };
+
+    function panelGetter(name)
+    {
+        return panels[name];
+    }
+    for (var panel in panels)
+        this.__defineGetter__(panel, bind(panelGetter, null, panel));
+}
+
+Panels.prototype = {
+    create: function(title, iconURL, pageURL, callback)
+    {
+        var id = "extension-panel-" + extensionServer.nextObjectId();
+        var request = {
+            command: "createPanel",
+            id: id,
+            title: title,
+            icon: expandURL(iconURL),
+            url: expandURL(pageURL)
+        };
+        extensionServer.sendRequest(request, callback && bind(callback, this, new ExtensionPanel(id)));
+    }
+}
+
+function PanelImpl(id)
+{
+    this._id = id;
+}
+
+function PanelWithSidebarImpl(id)
+{
+    PanelImpl.call(this, id);
+}
+
+PanelWithSidebarImpl.prototype = {
+    createSidebarPane: function(title, url, callback)
+    {
+        var id = "extension-sidebar-" + extensionServer.nextObjectId();
+        var request = {
+            command: "createSidebarPane",
+            panel: this._id,
+            id: id,
+            title: title,
+            url: expandURL(url)
+        };
+        function callbackWrapper()
+        {
+            callback(new ExtensionSidebarPane(id));
+        }
+        extensionServer.sendRequest(request, callback && callbackWrapper);
+    },
+
+    createWatchExpressionSidebarPane: function(title, callback)
+    {
+        var id = "watch-sidebar-" + extensionServer.nextObjectId();
+        var request = {
+            command: "createWatchExpressionSidebarPane",
+            panel: this._id,
+            id: id,
+            title: title
+        };
+        function callbackWrapper()
+        {
+            callback(new WatchExpressionSidebarPane(id));
+        }
+        extensionServer.sendRequest(request, callback && callbackWrapper);
+    }
+}
+
+PanelWithSidebarImpl.prototype.__proto__ = PanelImpl.prototype;
+
+function ElementsPanel()
+{
+    var id = "elements";
+    PanelWithSidebar.call(this, id);
+    this.onSelectionChanged = new EventSink("panel-objectSelected-" + id);
+}
+
+function ExtensionPanel(id)
+{
+    Panel.call(this, id);
+    this.onSearch = new EventSink("panel-search-" + id);
+}
+
+function ExtensionSidebarPaneImpl(id)
+{
+    this._id = id;
+}
+
+ExtensionSidebarPaneImpl.prototype = {
+    setHeight: function(height)
+    {
+        extensionServer.sendRequest({ command: "setSidebarHeight", id: this._id, height: height });
+    }
+}
+
+function WatchExpressionSidebarPaneImpl(id)
+{
+    ExtensionSidebarPaneImpl.call(this, id);
+    this.onUpdated = new EventSink("watch-sidebar-updated-" + id);
+}
+
+WatchExpressionSidebarPaneImpl.prototype = {
+    setExpression: function(expression, rootTitle)
+    {
+        extensionServer.sendRequest({ command: "setWatchSidebarContent", id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true });
+    },
+
+    setObject: function(jsonObject, rootTitle)
+    {
+        extensionServer.sendRequest({ command: "setWatchSidebarContent", id: this._id, expression: jsonObject, rootTitle: rootTitle });
+    }
+}
+
+WatchExpressionSidebarPaneImpl.prototype.__proto__ = ExtensionSidebarPaneImpl.prototype;
+
+function WatchExpressionSidebarPane(id)
+{
+    var impl = new WatchExpressionSidebarPaneImpl(id);
+    ExtensionSidebarPane.call(this, id, impl);
+}
+
+function Audits()
+{
+}
+
+Audits.prototype = {
+    addCategory: function(displayName, resultCount)
+    {
+        var id = "extension-audit-category-" + extensionServer.nextObjectId();
+        extensionServer.sendRequest({ command: "addAuditCategory", id: id, displayName: displayName, resultCount: resultCount });
+        return new AuditCategory(id);
+    }
+}
+
+function AuditCategoryImpl(id)
+{
+    function auditResultDispatch(request)
+    {
+        var auditResult = new AuditResult(request.arguments[0]);
+        try {
+            this._fire(auditResult);
+        } catch (e) {
+            console.error("Uncaught exception in extension audit event handler: " + e);
+            auditResult.done();
+        }
+    }
+    this._id = id;
+    this.onAuditStarted = new EventSink("audit-started-" + id, auditResultDispatch);
+}
+
+function AuditResultImpl(id)
+{
+    this._id = id;
+
+    var formatterTypes = [
+        "url",
+        "snippet",
+        "text"
+    ];
+    for (var i = 0; i < formatterTypes.length; ++i)
+        this[formatterTypes[i]] = bind(this._nodeFactory, null, formatterTypes[i]);
+}
+
+AuditResultImpl.prototype = {
+    addResult: function(displayName, description, severity, details)
+    {
+        // shorthand for specifying details directly in addResult().
+        if (details && !(details instanceof AuditResultNode))
+            details = details instanceof Array ? this.createNode.apply(this, details) : this.createNode(details);
+
+        var request = {
+            command: "addAuditResult",
+            resultId: this._id,
+            displayName: displayName,
+            description: description,
+            severity: severity,
+            details: details
+        };
+        extensionServer.sendRequest(request);
+    },
+
+    createResult: function()
+    {
+        var node = new AuditResultNode();
+        node.contents = Array.prototype.slice.call(arguments);
+        return node;
+    },
+
+    done: function()
+    {
+        extensionServer.sendRequest({ command: "stopAuditCategoryRun", resultId: this._id });
+    },
+
+    get Severity()
+    {
+        return apiPrivate.audits.Severity;
+    },
+
+    _nodeFactory: function(type)
+    {
+        return {
+            type: type,
+            arguments: Array.prototype.slice.call(arguments, 1)
+        };
+    }
+}
+
+function AuditResultNode(contents)
+{
+    this.contents = contents;
+    this.children = [];
+    this.expanded = false;
+}
+
+AuditResultNode.prototype = {
+    addChild: function()
+    {
+        var node = AuditResultImpl.prototype.createResult.apply(null, arguments);
+        this.children.push(node);
+        return node;
+    }
+};
+
+function InspectedWindow()
+{
+    this.onDOMContentLoaded = new EventSink("inspectedPageDOMContentLoaded");
+    this.onLoaded = new EventSink("inspectedPageLoaded");
+    this.onNavigated = new EventSink("inspectedURLChanged");
+}
+
+InspectedWindow.prototype = {
+    reload: function(userAgent)
+    {
+        return extensionServer.sendRequest({ command: "reload", userAgent: userAgent });
+    },
+
+    eval: function(expression, callback)
+    {
+        function callbackWrapper(result)
+        {
+            var value = result.value;
+            if (!result.isException)
+                value = value === "undefined" ? undefined : JSON.parse(value);
+            callback(value, result.isException);
+        }
+        return extensionServer.sendRequest({ command: "evaluateOnInspectedPage", expression: expression }, callback && callbackWrapper);
+    }
+}
+
+function ExtensionServerClient()
+{
+    this._callbacks = {};
+    this._handlers = {};
+    this._lastRequestId = 0;
+    this._lastObjectId = 0;
+
+    this.registerHandler("callback", bind(this._onCallback, this));
+
+    var channel = new MessageChannel();
+    this._port = channel.port1;
+    this._port.addEventListener("message", bind(this._onMessage, this), false);
+    this._port.start();
+
+    top.postMessage("registerExtension", [ channel.port2 ], "*");
+}
+
+ExtensionServerClient.prototype = {
+    sendRequest: function(message, callback)
+    {
+        if (typeof callback === "function")
+            message.requestId = this._registerCallback(callback);
+        return this._port.postMessage(message);
+    },
+
+    registerHandler: function(command, handler)
+    {
+        this._handlers[command] = handler;
+    },
+
+    nextObjectId: function()
+    {
+        return injectedScriptId + "_" + ++this._lastObjectId;
+    },
+
+    _registerCallback: function(callback)
+    {
+        var id = ++this._lastRequestId;
+        this._callbacks[id] = callback;
+        return id;
+    },
+
+    _onCallback: function(request)
+    {
+        if (request.requestId in this._callbacks) {
+            var callback = this._callbacks[request.requestId];
+            delete this._callbacks[request.requestId];
+            callback(request.result);
+        }
+    },
+
+    _onMessage: function(event)
+    {
+        var request = event.data;
+        var handler = this._handlers[request.command];
+        if (handler)
+            handler.call(this, request);
+    }
+}
+
+function expandURL(url)
+{
+    if (!url)
+        return url;
+    if (/^[^/]+:/.exec(url)) // See if url has schema.
+        return url;
+    var baseURL = location.protocol + "//" + location.hostname + location.port;
+    if (/^\//.exec(url))
+        return baseURL + url;
+    return baseURL + location.pathname.replace(/\/[^/]*$/,"/") + url;
+}
+
+function bind(func, thisObject)
+{
+    var args = Array.prototype.slice.call(arguments, 2);
+    return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); };
+}
+
+function populateInterfaceClass(interface, implementation)
+{
+    for (var member in implementation) {
+        if (member.charAt(0) === "_")
+            continue;
+        var value = implementation[member];
+        interface[member] = typeof value === "function" ? bind(value, implementation)
+            : interface[member] = implementation[member];
+    }
+}
+
+function declareInterfaceClass(implConstructor)
+{
+    return function()
+    {
+        var impl = { __proto__: implConstructor.prototype };
+        implConstructor.apply(impl, arguments);
+        populateInterfaceClass(this, impl);
+    }
+}
+
+var AuditCategory = declareInterfaceClass(AuditCategoryImpl);
+var AuditResult = declareInterfaceClass(AuditResultImpl);
+var EventSink = declareInterfaceClass(EventSinkImpl);
+var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
+var Panel = declareInterfaceClass(PanelImpl);
+var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
+var Resource = declareInterfaceClass(ResourceImpl);
+var WatchExpressionSidebarPane = declareInterfaceClass(WatchExpressionSidebarPaneImpl);
+
+var extensionServer = new ExtensionServerClient();
+
+webInspector = new InspectorExtensionAPI();
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPISchema.json b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPISchema.json
new file mode 100755
index 0000000..28084ba
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAPISchema.json
@@ -0,0 +1,513 @@
+[
+  {
+    "namespace": "experimental.webInspector.inspectedWindow",
+    "description": "Provides access to the window being inspected.",
+    "functions": [
+      {
+        "name": "eval",
+        "type": "function",
+        "description": "Evaluates a JavaScript expression in the context of inspected page (NOTE: the expression must evaluate to a JSON-compliant object, otherwise the exception is thrown)",
+        "parameters": [
+          {
+            "name": "expression",
+            "type": "string",
+            "description": "An expression to evaluate."
+          },
+          {
+            "name": "callback",
+            "type": "function",
+            "description": "A function called when evaluation completes.",
+            "parameters": [
+              {
+                "name": "result",
+                "type": "object",
+                "description": "The result of evaluation"
+              },
+              {
+                "name": "isException",
+                "type": "boolean",
+                "description": "Set if an exception was caught while evaluating the expression"
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    "events": [
+      {
+        "name": "onDOMContentLoaded",
+        "type": "function",
+        "description": "Fired after DOMContentLoaded event on inspected page is fired."
+      },
+      {
+        "name": "onLoaded",
+        "type": "function",
+        "description": "Fired after load event on inspected page is fired."
+      },
+      {
+        "name": "onNavigated",
+        "type": "function",
+        "description": "Fired when navigation occurs in the window being inspected."
+      }
+    ]
+  },
+  {
+    "namespace": "experimental.webInspector.panels",
+    "types": [
+      {
+        "id": "PanelWithSidebars",
+        "type": "object",
+        "isInstanceOf": "Panel",
+        "description": "A panel within Web Inspector UI that has sidebars.",
+        "functions": [
+          {
+            "name": "createSidebarPane",
+            "type": "function",
+            "description": "Creates a pane within panel's sidebar.",
+            "parameters": [
+              {
+                "name": "title",
+                "type": "string",
+                "description": "A text that is displayed in sidebar caption."
+              },
+              {
+                "name": "url",
+                "type": "string",
+                "description": "An URL of the page that represents the sidebar."
+              },
+              {
+                "name": "callback",
+                "type": "function",
+                "description": "A callback invoked when sidebar is created",
+                "parameters": [
+                  {
+                    "name": "result",
+                    "description": "An ExtensionSidebarPane object for created sidebar pane",
+                    "$ref": "ExtensionSidebarPane"
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            "name": "createWatchExpressionSidebarPane",
+            "type": "function",
+            "description": "Creates a pane with an object property tree (similar to a watch sidebar pane).",
+            "parameters": [
+              {
+                "name": "title",
+                "type": "string",
+                "description": "A text that is displayed in sidebar caption."
+              },
+              {
+                "name": "callback",
+                "type": "function",
+                "description": "A callback invoked when sidebar is created",
+                "parameters": [
+                  {
+                    "name": "result",
+                    "description": "A WatchExpressionSidebarPane object for created sidebar pane",
+                    "$ref": "WatchExpressionSidebarPane"
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      },
+      {
+        "id": "ElementsPanel",
+        "type": "object",
+        "isInstanceOf": "PanelWithSidebars",
+        "description": "Represents Elements panel",
+        "events": [
+          {
+            "name": "onSelectionChanged",
+            "description": "Fired when an objects is selected in the panel."
+          }
+        ]
+      },
+      {
+        "id": "ExtensionPanel",
+        "type": "object",
+        "isInstanceOf": "Panel",
+        "description": "Represents a panel created by extension",
+        "events": [
+          {
+            "name": "onSearch",
+            "description": "Fired upon a search action (start of a new search, search result navigation or search being canceled).",
+            "parameters": [
+              {
+                "name": "action",
+                "type": "string",
+                "description": "Type of search action being performed."
+              },
+              {
+                "name": "queryString",
+                "type": "string",
+                "optional": true,
+                "description": "Query string (only for 'performSearch')"
+              }
+            ]
+          }
+       	]
+      },
+      {
+        "id": "ExtensionSidebarPane",
+        "type": "object",
+        "description": "A sidebar created by the extension.",
+        "functions": [
+          {
+            "name": "setHeight",
+            "type": "function",
+            "description": "Sets the height of the sidebar.",
+            "parameters": [
+              {
+                "name": "height",
+                "type": "string",
+                "description": "A CSS-like size specification, e.g. '10px' or '12pt'"
+              }
+            ]
+          }
+        ]
+      },
+      {
+        "id": "WatchExpressionSidebarPane",
+        "type": "object",
+        "description": "A sidebar created by the extension.",
+        "functions": [
+          {
+            "name": "setHeight",
+            "type": "function",
+            "description": "Sets the height of the sidebar.",
+            "parameters": [
+              {
+                "name": "height",
+                "type": "string",
+                "description": "A CSS-like size specification, e.g. '10px' or '12pt'"
+              }
+            ]
+          },
+          {
+            "name": "setExpression",
+            "type": "function",
+            "description": "Sets an expression that is evaluated within the inspected page. The result is displayed in the sidebar pane.",
+            "parameters": [
+              {
+                "name": "expression",
+                "type": "string",
+                "description": "An expression to be evaluated in context of the inspected page. JavaScript objects and DOM nodes are displayed in an expandable tree similar to the console/watch."
+              },
+              {
+                "name": "rootTitle",
+                "type": "string",
+                "optional": true,
+                "description": "An optional title for the root of the expression tree."
+              }
+            ]
+          },
+          {
+            "name": "setObject",
+            "type": "function",
+            "description": "Sets a JSON-compliant object to be displayed in the sidebar pane.",
+            "parameters": [
+              {
+                "name": "jsonObject",
+                "type": "string",
+                "description": "An object to be displayed in context of the inspected page. Evaluated in the context of the caller (API client)."
+              },
+              {
+                "name": "rootTitle",
+                "type": "string",
+                "optional": true,
+                "description": "An optional title for the root of the expression tree."
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    "properties": {
+      "scripts": {
+        "$ref": "ScriptsPanel",
+        "description": "Scripts panel"
+      }
+    },
+    "functions": [
+      {
+        "name": "create",
+        "type": "function",
+        "description": "Creates an extension panel.",
+        "parameters": [
+          {
+            "name": "title",
+            "type": "string",
+            "description": "Title that is displayed under the extension icon in the toolbar."
+          },
+          {
+            "name": "iconURL",
+            "type": "string",
+            "description": "An URL of the toolbar icon."
+          },
+          {
+            "name": "pageURL",
+            "type": "string",
+            "description": "An URL of the page that represents this panel."
+          }
+        ],
+        "returns" : {
+          "$ref": "ExtensionPanel",
+          "description": "A panel that was created."
+        }
+      }
+    ]
+  },
+  {
+    "namespace": "experimental.webInspector.resources",
+    "types": [
+      {
+        "id": "Resource",
+        "type": "object",
+        "description": "Represents a resource (document, script, image etc). See HAR Specification for reference.",
+        "functions": [
+          {
+            "name": "getContent",
+            "type": "function",
+            "description": "Returns resource content.",
+            "parameters": [
+              {
+                "name": "callback",
+                "type": "function",
+                "description": "A function that is called upon request completion.",
+                "parameters": [
+                  {
+                    "name": "content",
+                    "type": "string",
+                    "description": "Resource content (potentially encoded)."
+                  },
+                  {
+                    "name": "encoding",
+                    "type": "string",
+                    "description": "Empty if content is not encoded, encoding name otherwise. Currently, only base64 supported."
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    "functions": [
+      {
+        "name": "getHAR",
+        "type": "function",
+        "description": "Returns HAR archive that contains all known resource objects.",
+        "parameters": [
+          {
+            "name": "callback",
+            "type": "function",
+            "description": "A function that is called upon request completion.",
+            "parameters": [
+              {
+                "name": "har",
+                "type": "object",
+                "description": "A HAR archieve. See HAR specification for details."
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    "events": [
+      {
+        "name": "onFinished",
+        "type": "function",
+        "description": "Fired when a resource request is finished and all resource data are available.",
+        "parameters": [
+          { "name": "resource", "$ref": "Resource" }
+        ]
+      }
+    ]
+  },
+  {
+    "namespace": "experimental.webInspector.audits",
+    "functions": [
+      {
+        "name": "addCategory",
+        "type": "function",
+        "description": "Adds an audit category.",
+        "parameters": [
+          { "name": "displayName", "type": "string", "description": "A display name for the category" },
+          { "name": "resultCount", "type": "number", "description": "The expected number of audit results in the category." }
+        ],
+        "returns": {
+          "$ref": "AuditCategory"
+        }
+      }
+    ],
+    "types": [
+      {
+        "id": "AuditCategory",
+        "type": "object",
+        "description": "A set of audit rules",
+        "events": [
+          {
+            "name": "onAuditStarted",
+            "type": "function",
+            "description": "Fired when the audit is started, if the category is enabled -- the extension is expected to begin executing audit rules.",
+            "parameters": [
+              { "name": "results", "$ref": "AuditResults" }
+            ]
+          }
+        ]
+      },
+      {
+        "id": "FormattedValue",
+        "type": "object",
+        "description": "A value returned from one of the formatters (an URL, code snippet etc), to be passed to createResult or addChild"
+      },
+      {
+        "id": "AuditResults",
+        "type": "object",
+        "description": "A collection of audit results for current run of the audit category",
+        "functions": [
+          {
+            "name": "addResult",
+            "type": "function",
+            "parameters": [
+              {
+                "name": "displayName",
+                "type": "string",
+                "description": "A concise, high-level description of audit rule result"
+              },
+              {
+                "name": "description",
+                "type": "string",
+                "description": "A detailed description of what the displayName means"
+              },
+              {
+                "name": "severity",
+                "$ref": "AuditResultSeverety"
+              },
+              {
+                "name": "details",
+                "$ref": "AuditResultNode",
+                "optional": true,
+                "description": "A subtree that appears under added result that may provide additional details on the violations found"
+              }
+            ]
+          },
+          {
+            "name": "createResult",
+            "type": "function",
+            "description": "Creates a result node that may be user as details parameters to addResult",
+            "parameters": [
+              {
+                "name": "content ...",
+                "choices": [
+                  { "type": "string" },
+                  { "$ref": "FormattedValue" }
+                ],
+                "description": "Either string or formatted values returned by one of AuditResult formatters (url, snippet etc)"
+              }
+            ],
+            "returns": {
+              "$ref": "AuditResultNode"
+            }
+          },
+          {
+            "name": "done",
+            "type": "function",
+            "description": "Signals the WebInspector Audits panel that the run of this category is over. Normally the run completes automatically when a number of added top-level results is equal to that declared when AuditCategory was created."
+          },
+          {
+            "name": "url",
+            "type": "function",
+            "description": "Render passed value as an URL in the Audits panel",
+            "parameters": [
+              { "name": "href", "type": "string", "description": "An URL that will appear as href value on resulting link" },
+              { "name": "displayText", "type": "string", "description": "A text that will appear to user", "optional": true }
+            ],
+            "returns": { "$ref": "FormattedValue" }
+          },
+          {
+            "name": "snippet",
+            "type": "function",
+            "description": "Render passed text as a code snippet in the Audits panel",
+            "parameters": [
+              { "name": "text", "type": "string", "description": "Snippet text" }
+            ],
+            "returns": { "$ref": "FormattedValue" }
+          }
+        ],
+        "properties": {
+          "Severity": {
+            "$ref": "AuditResultSeverity",
+            "description": "A class that contains possible values for audit result severities."
+          },
+          "text": {
+            "type": "string",
+            "description": "The contents of the node."
+          },
+          "children": {
+            "optional": true,
+            "type": "array",
+            "items": { "$ref": "AuditResultNode" },
+            "description": "Children of this node."
+          },
+          "expanded": {
+            "optional": "true",
+            "type": "boolean",
+            "description": "Whether the node is expanded by default."
+          }
+        }
+      },
+      {
+        "id": "AuditResultNode",
+        "type": "object",
+        "description": "A node in the audit result trees. Displays some content and optionally has children node",
+        "functions": [
+          {
+            "name": "addChild",
+            "description": "Adds another child node to this node",
+            "parameters": [
+              {
+                "name": "content ...",
+                "choices": [
+                  { "type": "string" },
+                  { "$ref": "FormattedValue" }
+                ],
+                "description": "Either string or formatted values returned by one of AuditResult formatters (url, snippet etc)"
+              }
+            ],
+            "returns": {
+              "$ref": "AuditResultNode"
+            }
+          }
+        ],
+        "properties": {
+          "expanded": {
+            "type": "boolean",
+            "description": "If set, the subtree will always be expanded"
+          }
+        }
+      },
+      {
+        "id": "AuditResultSeverity",
+        "type": "object",
+        "properties": {
+          "Info": {
+            "type": "string"
+          },
+          "Warning": {
+            "type": "string"
+          },
+          "Severe": {
+            "type": "string"
+          }
+        }
+      }
+    ]
+  }
+]
+
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAuditCategory.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAuditCategory.js
new file mode 100644
index 0000000..5d155d7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionAuditCategory.js
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ExtensionAuditCategory = function(id, displayName, ruleCount)
+{
+    this._id = id;
+    this._displayName = displayName;
+    this._ruleCount  = ruleCount;
+}
+
+WebInspector.ExtensionAuditCategory.prototype = {
+    // AuditCategory interface
+    get id()
+    {
+        return this._id;
+    },
+
+    get displayName()
+    {
+        return this._displayName;
+    },
+
+    get ruleCount()
+    {
+        return this._ruleCount;
+    },
+
+    run: function(resources, callback)
+    {
+        new WebInspector.ExtensionAuditCategoryResults(this, callback);
+    }
+}
+
+WebInspector.ExtensionAuditCategoryResults = function(category, callback)
+{
+    this._category = category;
+    this._pendingRules = category.ruleCount;
+    this._ruleCompletionCallback = callback;
+
+    this.id = category.id + "-" + ++WebInspector.ExtensionAuditCategoryResults._lastId;
+    WebInspector.extensionServer.startAuditRun(category, this);
+}
+
+WebInspector.ExtensionAuditCategoryResults.prototype = {
+    get complete()
+    {
+        return !this._pendingRules;
+    },
+
+    cancel: function()
+    {
+        while (!this.complete)
+            this._addResult(null);
+    },
+
+    addResult: function(displayName, description, severity, details)
+    {
+        var result = new WebInspector.AuditRuleResult(displayName);
+        result.addChild(description);
+        result.severity = severity;
+        if (details)
+            this._addNode(result, details);
+        this._addResult(result);
+    },
+
+    _addNode: function(parent, node)
+    {
+        var addedNode = parent.addChild(node.contents, node.expanded);
+        if (node.children) {
+            for (var i = 0; i < node.children.length; ++i)
+                this._addNode(addedNode, node.children[i]);
+        }
+    },
+
+    _addResult: function(result)
+    {
+        this._ruleCompletionCallback(result);
+        this._pendingRules--;
+        if (!this._pendingRules)
+            WebInspector.extensionServer.stopAuditRun(this);
+    }
+}
+
+WebInspector.ExtensionAuditCategoryResults._lastId = 0;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionCommon.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionCommon.js
new file mode 100644
index 0000000..8034001
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionCommon.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.commonExtensionSymbols = function(apiPrivate)
+{
+    
+    if (!apiPrivate.audits)
+        apiPrivate.audits = {};
+
+    apiPrivate.audits.Severity = {
+        Info: "info",
+        Warning: "warning",
+        Severe: "severe"
+    };
+}
+
+WebInspector.extensionAPI = {};
+
+WebInspector.commonExtensionSymbols(WebInspector.extensionAPI);
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionPanel.js
new file mode 100644
index 0000000..144d55d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionPanel.js
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ExtensionPanel = function(id, label, iconURL, options)
+{
+    this.toolbarItemLabel = label;
+    this._addStyleRule(".toolbar-item." + id + " .toolbar-icon", "background-image: url(" + iconURL + ");");
+    WebInspector.Panel.call(this, id);
+}
+
+WebInspector.ExtensionPanel.prototype = {
+    get defaultFocusedElement()
+    {
+        return this.sidebarTreeElement || this.element;
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this.bodyElement.style.left = width + "px";
+        this.resize();
+    },
+
+    searchCanceled: function(startingNewSearch)
+    {
+        WebInspector.extensionServer.notifySearchAction(this._id, "cancelSearch");
+        WebInspector.Panel.prototype.searchCanceled.apply(this, arguments);
+    },
+
+    performSearch: function(query)
+    {
+        WebInspector.extensionServer.notifySearchAction(this._id, "performSearch", query);
+        WebInspector.Panel.prototype.performSearch.apply(this, arguments);
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        WebInspector.extensionServer.notifySearchAction(this._id, "nextSearchResult");
+        WebInspector.Panel.prototype.jumpToNextSearchResult.call(this);
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        WebInspector.extensionServer.notifySearchAction(this._id, "previousSearchResult");
+        WebInspector.Panel.prototype.jumpToPreviousSearchResult.call(this);
+    },
+
+    _addStyleRule: function(selector, body)
+    {
+        var style = document.createElement("style");
+        style.textContent = selector + " { " + body + " }";
+        document.head.appendChild(style);
+    }
+}
+
+WebInspector.ExtensionPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.ExtensionWatchSidebarPane = function(title, id)
+{
+    WebInspector.SidebarPane.call(this, title);
+    this._id = id;
+}
+
+WebInspector.ExtensionWatchSidebarPane.prototype = {
+    setObject: function(object, title)
+    {
+        this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title);
+    },
+
+    setExpression: function(expression, title)
+    {
+        InspectorBackend.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title));
+    },
+
+    _onEvaluate: function(title, result)
+    {
+        this._setObject(WebInspector.RemoteObject.fromPayload(result), title);
+    },
+
+    _setObject: function(object, title)
+    {
+        this.bodyElement.removeChildren();
+        var section = new WebInspector.ObjectPropertiesSection(object, title, null, true);
+        if (!title)
+            section.headerElement.addStyleClass("hidden");
+        section.expanded = true;
+        this.bodyElement.appendChild(section.element);
+        WebInspector.extensionServer.notifyExtensionWatchSidebarUpdated(this._id);
+    }
+}
+
+WebInspector.ExtensionWatchSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionRegistryStub.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionRegistryStub.js
new file mode 100644
index 0000000..a9c96ef
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionRegistryStub.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!window.InspectorExtensionRegistry) {
+
+WebInspector.InspectorExtensionRegistryStub = function()
+{
+}
+
+WebInspector.InspectorExtensionRegistryStub.prototype = {
+    getExtensionsAsync: function()
+    {
+    }
+};
+
+InspectorExtensionRegistry = new WebInspector.InspectorExtensionRegistryStub();
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionServer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionServer.js
new file mode 100644
index 0000000..7d33b73
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ExtensionServer.js
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ExtensionServer = function()
+{
+    this._clientObjects = {};
+    this._handlers = {};
+    this._subscribers = {};
+    this._extraHeaders = {};
+    this._status = new WebInspector.ExtensionStatus();
+
+    this._registerHandler("addRequestHeaders", this._onAddRequestHeaders.bind(this));
+    this._registerHandler("addAuditCategory", this._onAddAuditCategory.bind(this));
+    this._registerHandler("addAuditResult", this._onAddAuditResult.bind(this));
+    this._registerHandler("createPanel", this._onCreatePanel.bind(this));
+    this._registerHandler("createSidebarPane", this._onCreateSidebar.bind(this));
+    this._registerHandler("createWatchExpressionSidebarPane", this._onCreateWatchExpressionSidebarPane.bind(this));
+    this._registerHandler("evaluateOnInspectedPage", this._onEvaluateOnInspectedPage.bind(this));
+    this._registerHandler("getHAR", this._onGetHAR.bind(this));
+    this._registerHandler("getResourceContent", this._onGetResourceContent.bind(this));
+    this._registerHandler("log", this._onLog.bind(this));
+    this._registerHandler("reload", this._onReload.bind(this));
+    this._registerHandler("setSidebarHeight", this._onSetSidebarHeight.bind(this));
+    this._registerHandler("setWatchSidebarContent", this._onSetWatchSidebarContent.bind(this));
+    this._registerHandler("stopAuditCategoryRun", this._onStopAuditCategoryRun.bind(this));
+    this._registerHandler("subscribe", this._onSubscribe.bind(this));
+    this._registerHandler("unsubscribe", this._onUnsubscribe.bind(this));
+
+    window.addEventListener("message", this._onWindowMessage.bind(this), false);
+}
+
+WebInspector.ExtensionServer.prototype = {
+    notifyPanelShown: function(panelName)
+    {
+        this._postNotification("panel-shown-" + panelName);
+    },
+
+    notifyObjectSelected: function(panelId, objectId)
+    {
+        this._postNotification("panel-objectSelected-" + panelId, objectId);
+    },
+
+    notifySearchAction: function(panelId, action, searchString)
+    {
+        this._postNotification("panel-search-" + panelId, action, searchString);
+    },
+
+    notifyPageLoaded: function(milliseconds)
+    {
+        this._postNotification("inspectedPageLoaded", milliseconds);
+    },
+
+    notifyPageDOMContentLoaded: function(milliseconds)
+    {
+        this._postNotification("inspectedPageDOMContentLoaded", milliseconds);
+    },
+
+    notifyInspectedURLChanged: function()
+    {
+        this._postNotification("inspectedURLChanged");
+    },
+
+    notifyInspectorReset: function()
+    {
+        this._postNotification("reset");
+    },
+
+    notifyExtensionWatchSidebarUpdated: function(id)
+    {
+        this._postNotification("watch-sidebar-updated-" + id);
+    },
+
+    startAuditRun: function(category, auditRun)
+    {
+        this._clientObjects[auditRun.id] = auditRun;
+        this._postNotification("audit-started-" + category.id, auditRun.id);
+    },
+
+    stopAuditRun: function(auditRun)
+    {
+        delete this._clientObjects[auditRun.id];
+    },
+
+    _notifyResourceFinished: function(event)
+    {
+        var resource = event.data;
+        this._postNotification("resource-finished", resource.identifier, (new WebInspector.HAREntry(resource)).build());
+    },
+
+    _postNotification: function(type, details)
+    {
+        var subscribers = this._subscribers[type];
+        if (!subscribers)
+            return;
+        var message = {
+            command: "notify-" + type,
+            arguments: Array.prototype.slice.call(arguments, 1)
+        };
+        for (var i = 0; i < subscribers.length; ++i)
+            subscribers[i].postMessage(message);
+    },
+
+    _onSubscribe: function(message, port)
+    {
+        var subscribers = this._subscribers[message.type];
+        if (subscribers)
+            subscribers.push(port);
+        else
+            this._subscribers[message.type] = [ port ];
+    },
+
+    _onUnsubscribe: function(message, port)
+    {
+        var subscribers = this._subscribers[message.type];
+        if (!subscribers)
+            return;
+        subscribers.remove(port);
+        if (!subscribers.length)
+            delete this._subscribers[message.type];
+    },
+
+    _onAddRequestHeaders: function(message)
+    {
+        var id = message.extensionId;
+        if (typeof id !== "string")
+            return this._status.E_BADARGTYPE("extensionId", typeof id, "string");
+        var extensionHeaders = this._extraHeaders[id];
+        if (!extensionHeaders) {
+            extensionHeaders = {};
+            this._extraHeaders[id] = extensionHeaders;
+        }
+        for (name in message.headers)
+            extensionHeaders[name] = message.headers[name];
+        var allHeaders = {};
+        for (extension in this._extraHeaders) {
+            var headers = this._extraHeaders[extension];
+            for (name in headers) {
+                if (typeof headers[name] === "string")
+                    allHeaders[name] = headers[name];
+            }
+        }
+        InspectorBackend.setExtraHeaders(allHeaders);
+    },
+
+    _onCreatePanel: function(message, port)
+    {
+        var id = message.id;
+        // The ids are generated on the client API side and must be unique, so the check below
+        // shouldn't be hit unless someone is bypassing the API.
+        if (id in this._clientObjects || id in WebInspector.panels)
+            return this._status.E_EXISTS(id);
+        var panel = new WebInspector.ExtensionPanel(id, message.title, message.icon);
+        this._clientObjects[id] = panel;
+
+        var toolbarElement = document.getElementById("toolbar");
+        var lastToolbarItem = WebInspector.panelOrder[WebInspector.panelOrder.length - 1].toolbarItem;
+        WebInspector.addPanelToolbarIcon(toolbarElement, panel, lastToolbarItem);
+        WebInspector.panels[id] = panel;
+        var iframe = this._createClientIframe(panel.element, message.url);
+        iframe.style.height = "100%";
+        return this._status.OK();
+    },
+
+    _onCreateSidebar: function(message)
+    {
+        var sidebar = this._createSidebar(message, WebInspector.SidebarPane);
+        if (sidebar.isError)
+            return sidebar;
+        this._createClientIframe(sidebar.bodyElement, message.url);
+        return this._status.OK();
+    },
+
+    _onCreateWatchExpressionSidebarPane: function(message)
+    {
+        var sidebar = this._createSidebar(message, WebInspector.ExtensionWatchSidebarPane);
+        return sidebar.isError ? sidebar : this._status.OK();
+    },
+
+    _createSidebar: function(message, constructor)
+    {
+        var panel = WebInspector.panels[message.panel];
+        if (!panel)
+            return this._status.E_NOTFOUND(message.panel);
+        if (!panel.sidebarElement || !panel.sidebarPanes)
+            return this._status.E_NOTSUPPORTED();
+        var id = message.id;
+        var sidebar = new constructor(message.title, message.id);
+        this._clientObjects[id] = sidebar;
+        panel.sidebarPanes[id] = sidebar;
+        panel.sidebarElement.appendChild(sidebar.element);
+
+        return sidebar;
+    },
+
+    _createClientIframe: function(parent, url, requestId, port)
+    {
+        var iframe = document.createElement("iframe");
+        iframe.src = url;
+        iframe.style.width = "100%";
+        parent.appendChild(iframe);
+        return iframe;
+    },
+
+    _onSetSidebarHeight: function(message)
+    {
+        var sidebar = this._clientObjects[message.id];
+        if (!sidebar)
+            return this._status.E_NOTFOUND(message.id);
+        sidebar.bodyElement.firstChild.style.height = message.height;
+    },
+
+    _onSetWatchSidebarContent: function(message)
+    {
+        var sidebar = this._clientObjects[message.id];
+        if (!sidebar)
+            return this._status.E_NOTFOUND(message.id);
+        if (message.evaluateOnPage)
+            sidebar.setExpression(message.expression, message.rootTitle);
+        else
+            sidebar.setObject(message.expression, message.rootTitle);
+    },
+
+    _onLog: function(message)
+    {
+        WebInspector.log(message.message);
+    },
+
+    _onReload: function(message)
+    {
+        if (typeof message.userAgent === "string")
+            InspectorBackend.setUserAgentOverride(message.userAgent);
+
+        InspectorBackend.reloadPage(false);
+        return this._status.OK();
+    },
+
+    _onEvaluateOnInspectedPage: function(message, port)
+    {
+        function callback(resultPayload)
+        {
+            var resultObject = WebInspector.RemoteObject.fromPayload(resultPayload);
+            var result = {};
+            if (resultObject.isError())
+                result.isException = true;
+            result.value = resultObject.description;
+            this._dispatchCallback(message.requestId, port, result);
+        }
+        var evalExpression = "JSON.stringify(eval(unescape('" + escape(message.expression) + "')));";
+        InspectorBackend.evaluate(evalExpression, "none", true, callback.bind(this));
+    },
+
+    _onRevealAndSelect: function(message)
+    {
+        if (message.panelId === "resources" && type === "resource")
+            return this._onRevealAndSelectResource(message);
+        else
+            return this._status.E_NOTSUPPORTED(message.panelId, message.type);
+    },
+
+    _onRevealAndSelectResource: function(message)
+    {
+        var id = message.id;
+        var resource = null;
+
+        resource = WebInspector.networkResourceById(id) || WebInspector.resourceForURL(id);
+        if (!resource)
+            return this._status.E_NOTFOUND(typeof id + ": " + id);
+
+        WebInspector.panels.resources.showResource(resource, message.line);
+        WebInspector.showPanel("resources");
+    },
+
+    _dispatchCallback: function(requestId, port, result)
+    {
+        port.postMessage({ command: "callback", requestId: requestId, result: result });
+    },
+
+    _onGetHAR: function(request)
+    {
+        var harLog = new WebInspector.HARLog();
+        harLog.includeResourceIds = true;
+        return harLog.build();
+    },
+
+    _onGetResourceContent: function(message, port)
+    {
+        function onContentAvailable(content, encoded)
+        {
+            var response = {
+                encoding: encoded ? "base64" : "",
+                content: content
+            };
+            this._dispatchCallback(message.requestId, port, response);
+        }
+        var resource = WebInspector.networkResourceById(message.id);
+        if (!resource)
+            return this._status.E_NOTFOUND(message.id);
+        resource.requestContent(onContentAvailable.bind(this));
+    },
+
+    _onAddAuditCategory: function(request)
+    {
+        var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.resultCount);
+        if (WebInspector.panels.audits.getCategory(category.id))
+            return this._status.E_EXISTS(category.id);
+        this._clientObjects[request.id] = category;
+        WebInspector.panels.audits.addCategory(category);
+    },
+
+    _onAddAuditResult: function(request)
+    {
+        var auditResult = this._clientObjects[request.resultId];
+        if (!auditResult)
+            return this._status.E_NOTFOUND(request.resultId);
+        try {
+            auditResult.addResult(request.displayName, request.description, request.severity, request.details);
+        } catch (e) {
+            return e;
+        }
+        return this._status.OK();
+    },
+
+    _onStopAuditCategoryRun: function(request)
+    {
+        var auditRun = this._clientObjects[request.resultId];
+        if (!auditRun)
+            return this._status.E_NOTFOUND(request.resultId);
+        auditRun.cancel();
+    },
+
+    initExtensions: function()
+    {
+        // The networkManager is normally created after the ExtensionServer is constructed, but before initExtensions() is called.
+        WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._notifyResourceFinished, this);
+
+        InspectorExtensionRegistry.getExtensionsAsync();
+    },
+
+    _addExtensions: function(extensions)
+    {
+        // See ExtensionAPI.js and ExtensionCommon.js for details.
+        InspectorFrontendHost.setExtensionAPI(this._buildExtensionAPIInjectedScript());
+        for (var i = 0; i < extensions.length; ++i) {
+            var extension = extensions[i];
+            try {
+                if (!extension.startPage)
+                    return;
+                var iframe = document.createElement("iframe");
+                iframe.src = extension.startPage;
+                iframe.style.display = "none";
+                document.body.appendChild(iframe);
+            } catch (e) {
+                console.error("Failed to initialize extension " + extension.startPage + ":" + e);
+            }
+        }
+    },
+
+    _buildExtensionAPIInjectedScript: function()
+    {
+        var resourceTypes = {};
+        var resourceTypeProperties = Object.getOwnPropertyNames(WebInspector.Resource.Type);
+        for (var i = 0; i < resourceTypeProperties.length; ++i) {
+             var propName = resourceTypeProperties[i];
+             var propValue = WebInspector.Resource.Type[propName];
+             if (typeof propValue === "number")
+                 resourceTypes[propName] = WebInspector.Resource.Type.toString(propValue);
+        }
+        var platformAPI = WebInspector.buildPlatformExtensionAPI ? WebInspector.buildPlatformExtensionAPI() : "";
+        return "(function(){ " +
+            "var apiPrivate = {};" +
+            "(" + WebInspector.commonExtensionSymbols.toString() + ")(apiPrivate);" +
+            "(" + WebInspector.injectedExtensionAPI.toString() + ").apply(this, arguments);" +
+            platformAPI +
+            "})";
+    },
+
+    _onWindowMessage: function(event)
+    {
+        if (event.data !== "registerExtension")
+            return;
+        var port = event.ports[0];
+        port.addEventListener("message", this._onmessage.bind(this), false);
+        port.start();
+    },
+
+    _onmessage: function(event)
+    {
+        var request = event.data;
+        var result;
+
+        if (request.command in this._handlers)
+            result = this._handlers[request.command](request, event.target);
+        else
+            result = this._status.E_NOTSUPPORTED(request.command);
+
+        if (result && request.requestId)
+            this._dispatchCallback(request.requestId, event.target, result);
+    },
+
+    _registerHandler: function(command, callback)
+    {
+        this._handlers[command] = callback;
+    }
+}
+
+WebInspector.ExtensionServer._statuses =
+{
+    OK: "",
+    E_EXISTS: "Object already exists: %s",
+    E_BADARG: "Invalid argument %s: %s",
+    E_BADARGTYPE: "Invalid type for argument %s: got %s, expected %s",
+    E_NOTFOUND: "Object not found: %s",
+    E_NOTSUPPORTED: "Object does not support requested operation: %s",
+}
+
+WebInspector.ExtensionStatus = function()
+{
+    function makeStatus(code)
+    {
+        var description = WebInspector.ExtensionServer._statuses[code] || code;
+        var details = Array.prototype.slice.call(arguments, 1);
+        var status = { code: code, description: description, details: details };
+        if (code !== "OK") {
+            status.isError = true;
+            console.log("Extension server error: " + String.vsprintf(description, details));
+        }
+        return status;
+    }
+    for (status in WebInspector.ExtensionServer._statuses)
+        this[status] = makeStatus.bind(null, status);
+}
+
+WebInspector.addExtensions = function(extensions)
+{
+    WebInspector.extensionServer._addExtensions(extensions);
+}
+
+WebInspector.extensionServer = new WebInspector.ExtensionServer();
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/FontView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/FontView.js
new file mode 100644
index 0000000..82559ef
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/FontView.js
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.FontView = function(resource)
+{
+    WebInspector.ResourceView.call(this, resource);
+
+    this.element.addStyleClass("font");
+}
+
+WebInspector.FontView.prototype = {
+    hasContent: function()
+    {
+        return true;
+    },
+
+    _createContentIfNeeded: function()
+    {
+        if (this.fontPreviewElement)
+            return;
+
+        var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier;
+
+        this.fontStyleElement = document.createElement("style");
+        this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
+        document.head.appendChild(this.fontStyleElement);
+
+        this.fontPreviewElement = document.createElement("div");
+        this.element.appendChild(this.fontPreviewElement);
+
+        this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
+        this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
+        this._lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1;
+
+        this.updateFontPreviewSize();
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.ResourceView.prototype.show.call(this, parentElement);
+        this._createContentIfNeeded();
+        this.updateFontPreviewSize();
+    },
+
+    resize: function()
+    {
+        this.updateFontPreviewSize();
+        WebInspector.ResourceView.prototype.resize.call(this);
+    },
+
+    updateFontPreviewSize: function()
+    {
+        if (!this.fontPreviewElement || !this.visible)
+            return;
+
+        const measureFontSize = 50;
+        this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null);
+        this.fontPreviewElement.style.setProperty("position", "absolute", null);
+        this.fontPreviewElement.style.removeProperty("height");
+
+        const height = this.fontPreviewElement.offsetHeight;
+        const width = this.fontPreviewElement.offsetWidth;
+
+        // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar.
+        const containerWidth = this.element.offsetWidth - 50;
+
+        if (!height || !width || !containerWidth) {
+            this.fontPreviewElement.style.removeProperty("font-size");
+            this.fontPreviewElement.style.removeProperty("position");
+            return;
+        }
+
+        var realLineHeight = Math.floor(height / this._lineCount);
+        var fontSizeLineRatio = measureFontSize / realLineHeight;
+        var widthRatio = containerWidth / width;
+        var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 2;
+
+        this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
+        this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null);
+        this.fontPreviewElement.style.removeProperty("position");
+    }
+}
+
+WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/GoToLineDialog.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/GoToLineDialog.js
new file mode 100644
index 0000000..f246159
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/GoToLineDialog.js
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.GoToLineDialog = function(view)
+{
+    this._element = document.createElement("div");
+    this._element.className = "go-to-line-dialog";
+    this._element.addEventListener("keydown", this._onKeyDown.bind(this), false);
+    this._closeKeys = [
+        WebInspector.KeyboardShortcut.Keys.Enter.code,
+        WebInspector.KeyboardShortcut.Keys.Esc.code,
+    ];
+
+    var dialogWindow = this._element;
+
+    dialogWindow.createChild("label").innerText = WebInspector.UIString("Go to line: ");
+
+    this._input = dialogWindow.createChild("input");
+    this._input.setAttribute("type", "text");
+    this._input.setAttribute("size", 6);
+    var linesCount = view.textModel.linesCount;
+    if (linesCount)
+        this._input.setAttribute("title", WebInspector.UIString("1 - %d", linesCount));
+    var blurHandler = this._onBlur.bind(this);
+    this._input.addEventListener("blur", blurHandler, false);
+    
+
+    var go = dialogWindow.createChild("button");
+    go.innerText = WebInspector.UIString("Go");
+    go.addEventListener("click", this._onClick.bind(this), false);
+    go.addEventListener("mousedown", function(e) {
+        // Ok button click will close the dialog, removing onBlur listener
+        // to let click event be handled.
+        this._input.removeEventListener("blur", blurHandler, false);
+    }.bind(this), false);
+
+    this._view = view;
+    view.element.appendChild(this._element);
+
+    this._previousFocusElement = WebInspector.currentFocusElement;
+    WebInspector.currentFocusElement = this._input;
+    this._input.select();
+}
+
+WebInspector.GoToLineDialog.show = function(sourceView)
+{
+    if (this._instance)
+        return;
+    this._instance = new WebInspector.GoToLineDialog(sourceView);
+}
+
+WebInspector.GoToLineDialog.prototype = {
+    _hide: function()
+    {
+        if (this._isHiding)
+            return;
+        this._isHiding = true;
+
+        WebInspector.currentFocusElement = this._previousFocusElement;
+        WebInspector.GoToLineDialog._instance = null;
+        this._element.parentElement.removeChild(this._element);
+    },
+
+    _onBlur: function(event)
+    {
+        this._hide();
+    },
+
+    _onKeyDown: function(event)
+    {
+        if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) {
+            event.preventDefault();
+            return;
+        }
+
+        if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code)
+            this._highlightSelectedLine();
+
+        if (this._closeKeys.indexOf(event.keyCode) >= 0) {
+            this._hide();
+            event.stopPropagation();
+        }
+    },
+
+    _onClick: function(event)
+    {
+        this._highlightSelectedLine();
+        this._hide();
+    },
+
+    _highlightSelectedLine: function()
+    {
+        var value = this._input.value;
+        var lineNumber = parseInt(value, 10);
+        if (!isNaN(lineNumber) && lineNumber > 0) {
+            lineNumber = Math.min(lineNumber, this._view.textModel.linesCount);
+            this._view.highlightLine(lineNumber);
+        }
+    }
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/HAREntry.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HAREntry.js
new file mode 100644
index 0000000..4d690b3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HAREntry.js
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// See http://groups.google.com/group/http-archive-specification/web/har-1-2-spec
+// for HAR specification.
+
+WebInspector.HAREntry = function(resource)
+{
+    this._resource = resource;
+}
+
+WebInspector.HAREntry.prototype = {
+    build: function()
+    {
+        return {
+            pageref: this._resource.documentURL,
+            startedDateTime: new Date(this._resource.startTime * 1000),
+            time: WebInspector.HAREntry._toMilliseconds(this._resource.duration),
+            request: this._buildRequest(),
+            response: this._buildResponse(),
+            // cache: {...}, -- Not supproted yet.
+            timings: this._buildTimings()
+        };
+    },
+
+    _buildRequest: function()
+    {
+        var res = {
+            method: this._resource.requestMethod,
+            url: this._resource.url,
+            // httpVersion: "HTTP/1.1" -- Not available.
+            headers: this._buildHeaders(this._resource.requestHeaders),
+            headersSize: -1, // Not available.
+            bodySize: -1 // Not available.
+        };
+        if (this._resource.queryParameters)
+            res.queryString = this._buildParameters(this._resource.queryParameters);
+        if (this._resource.requestFormData)
+            res.postData = this._buildPostData();
+        if (this._resource.requestCookies)
+            res.cookies = this._buildCookies(this._resource.requestCookies);
+        return res;
+    },
+
+    _buildResponse: function()
+    {
+        var res = {
+            status: this._resource.statusCode,
+            statusText: this._resource.statusText,
+            // "httpVersion": "HTTP/1.1" -- Not available.
+            headers: this._buildHeaders(this._resource.responseHeaders),
+            content: this._buildContent(),
+            redirectURL: this._resource.responseHeaderValue("Location") || "",
+            headersSize: -1, // Not available.
+            bodySize: this._resource.resourceSize
+        };
+        if (this._resource.responseCookies)
+            res.cookies = this._buildCookies(this._resource.responseCookies);
+        return res;
+    },
+
+    _buildContent: function()
+    {
+        return {
+            size: this._resource.resourceSize,
+            // compression: 0, -- Not available.
+            mimeType: this._resource.mimeType,
+            // text: -- Not available.
+        };
+    },
+
+    _buildTimings: function()
+    {
+        var waitForConnection = this._interval("connectStart", "connectEnd");
+        var blocked;
+        var connect;
+        var dns = this._interval("dnsStart", "dnsEnd");
+        var send = this._interval("sendStart", "sendEnd");
+        var ssl = this._interval("sslStart", "sslEnd");
+
+        if (ssl !== -1 && send !== -1)
+            send -= ssl;
+
+        if (this._resource.connectionReused) {
+            connect = -1;
+            blocked = waitForConnection;
+        } else {
+            blocked = 0;
+            connect = waitForConnection;
+            if (dns !== -1)
+                connect -= dns;
+        }
+
+        return {
+            blocked: blocked,
+            dns: dns,
+            connect: connect,
+            send: send,
+            wait: this._interval("sendEnd", "receiveHeadersEnd"),
+            receive: WebInspector.HAREntry._toMilliseconds(this._resource.receiveDuration),
+            ssl: ssl
+        };
+    },
+
+    _buildHeaders: function(headers)
+    {
+        var result = [];
+        for (var name in headers)
+            result.push({ name: name, value: headers[name] });
+        return result;
+    },
+
+    _buildPostData: function()
+    {
+        var res = {
+            mimeType: this._resource.requestHeaderValue("Content-Type"),
+            text: this._resource.requestFormData
+        };
+        if (this._resource.formParameters)
+           res.params = this._buildParameters(this._resource.formParameters);
+        return res;
+    },
+
+    _buildParameters: function(parameters)
+    {
+        return parameters.slice();
+    },
+
+    _buildCookies: function(cookies)
+    {
+        return cookies.map(this._buildCookie.bind(this));
+    },
+
+    _buildCookie: function(cookie)
+    {
+        
+        return {
+            name: cookie.name,
+            value: cookie.value,
+            path: cookie.path,
+            domain: cookie.domain,
+            expires: cookie.expires(new Date(this._resource.startTime * 1000)),
+            httpOnly: cookie.httpOnly,
+            secure: cookie.secure
+        };
+    },
+
+    _interval: function(start, end)
+    {
+        var timing = this._resource.timing;
+        if (!timing)
+            return -1;
+        var startTime = timing[start];
+        return typeof startTime !== "number" || startTime === -1 ? -1 : Math.round(timing[end] - startTime);
+    }
+}
+
+WebInspector.HAREntry._toMilliseconds = function(time)
+{
+    return time === -1 ? -1 : Math.round(time * 1000);
+}
+
+WebInspector.HARLog = function()
+{
+    this.includeResourceIds = false;
+}
+
+WebInspector.HARLog.prototype = {
+    build: function()
+    {
+        var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);
+        
+        return {
+            version: "1.2",
+            creator: {
+                name: "WebInspector",
+                version: webKitVersion ? webKitVersion[1] : "n/a"
+            },
+            pages: this._buildPages(),
+            entries: WebInspector.networkResources.map(this._convertResource.bind(this))
+        }
+    },
+
+    _buildPages: function()
+    {
+        return [
+            {
+                startedDateTime: new Date(WebInspector.mainResource.startTime * 1000),
+                id: WebInspector.mainResource.documentURL,
+                title: "",
+                pageTimings: this.buildMainResourceTimings()
+            }
+        ];
+    },
+
+    buildMainResourceTimings: function()
+    {
+        return {
+             onContentLoad: this._pageEventTime(WebInspector.mainResourceDOMContentTime),
+             onLoad: this._pageEventTime(WebInspector.mainResourceLoadTime),
+        }
+    },
+
+    _convertResource: function(resource)
+    {
+        var entry = (new WebInspector.HAREntry(resource)).build();
+        if (this.includeResourceIds)
+            entry._resourceId = resource.identifier;
+        return entry;
+    },
+
+    _pageEventTime: function(time)
+    {
+        var startTime = WebInspector.mainResource.startTime;
+        if (time === -1 || startTime === -1)
+            return -1;
+        return WebInspector.HAREntry._toMilliseconds(time - startTime);
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshot.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshot.js
new file mode 100644
index 0000000..ef450af
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshot.js
@@ -0,0 +1,909 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.HeapSnapshotArraySlice = function(snapshot, arrayName, start, end)
+{
+    // Note: we don't reference snapshot contents directly to avoid
+    // holding references to big chunks of data.
+    this._snapshot = snapshot;
+    this._arrayName = arrayName;
+    this._start = start;
+    this.length = end - start;
+}
+
+WebInspector.HeapSnapshotArraySlice.prototype = {
+    item: function(index)
+    {
+        return this._snapshot[this._arrayName][this._start + index];
+    }
+}
+
+WebInspector.HeapSnapshotEdge = function(snapshot, edges, edgeIndex)
+{
+    this._snapshot = snapshot;
+    this._edges = edges;
+    this.edgeIndex = edgeIndex || 0;
+}
+
+WebInspector.HeapSnapshotEdge.prototype = {
+    clone: function()
+    {
+        return new WebInspector.HeapSnapshotEdge(this._snapshot, this._edges, this.edgeIndex);
+    },
+
+    get hasStringName()
+    {
+        if (!this.isShortcut)
+            return this._hasStringName;
+        return isNaN(parseInt(this._name, 10));
+    },
+
+    get isElement()
+    {
+        return this._type() === this._snapshot._edgeElementType;
+    },
+
+    get isHidden()
+    {
+        return this._type() === this._snapshot._edgeHiddenType;
+    },
+
+    get isInternal()
+    {
+        return this._type() === this._snapshot._edgeInternalType;
+    },
+
+    get isShortcut()
+    {
+        return this._type() === this._snapshot._edgeShortcutType;
+    },
+
+    get name()
+    {
+        if (!this.isShortcut)
+            return this._name;
+        var numName = parseInt(this._name, 10);
+        return isNaN(numName) ? this._name : numName;
+    },
+
+    get node()
+    {
+        return new WebInspector.HeapSnapshotNode(this._snapshot, this.nodeIndex);
+    },
+
+    get nodeIndex()
+    {
+        return this._edges.item(this.edgeIndex + this._snapshot._edgeToNodeOffset);
+    },
+
+    get rawEdges()
+    {
+        return this._edges;
+    },
+
+    toString: function()
+    {
+        switch (this.type) {
+        case "context": return "->" + this.name;
+        case "element": return "[" + this.name + "]";
+        case "property":
+            return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]";
+        case "shortcut":
+            var name = this.name;
+            if (typeof name === "string")
+                return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]";
+            else
+                return "[" + this.name + "]";
+        case "internal":
+        case "hidden":
+            return "{" + this.name + "}";
+        };
+        return "?" + this.name + "?";
+    },
+
+    get type()
+    {
+        return this._snapshot._edgeTypes[this._type()];
+    },
+
+    get _hasStringName()
+    {
+        return !this.isElement && !this.isHidden;
+    },
+
+    get _name()
+    {
+        return this._hasStringName ? this._snapshot._strings[this._nameOrIndex] : this._nameOrIndex;
+    },
+
+    get _nameOrIndex()
+    {
+        return this._edges.item(this.edgeIndex + this._snapshot._edgeNameOffset);
+    },
+
+    _type: function()
+    {
+        return this._edges.item(this.edgeIndex + this._snapshot._edgeTypeOffset);
+    }
+};
+
+WebInspector.HeapSnapshotEdgeIterator = function(edge)
+{
+    this.edge = edge;
+}
+
+WebInspector.HeapSnapshotEdgeIterator.prototype = {
+    first: function()
+    {
+        this.edge.edgeIndex = 0;
+    },
+
+    hasNext: function()
+    {
+        return this.edge.edgeIndex < this.edge._edges.length;
+    },
+
+    get index()
+    {
+        return this.edge.edgeIndex;
+    },
+
+    set index(newIndex)
+    {
+        this.edge.edgeIndex = newIndex;
+    },
+
+    get item()
+    {
+        return this.edge;
+    },
+
+    next: function()
+    {
+        this.edge.edgeIndex += this.edge._snapshot._edgeFieldsCount;
+    }
+};
+
+WebInspector.HeapSnapshotNode = function(snapshot, nodeIndex)
+{
+    this._snapshot = snapshot;
+    this._firstNodeIndex = nodeIndex;
+    this.nodeIndex = nodeIndex;
+}
+
+WebInspector.HeapSnapshotNode.prototype = {
+    get className()
+    {
+        switch (this.type) {
+        case "hidden":
+            return WebInspector.UIString("(system)");
+        case "object":
+            return this.name;
+        case "code":
+            return WebInspector.UIString("(compiled code)");
+        default:
+            return "(" + this.type + ")";
+        }
+    },
+
+    dominatorIndex: function()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._dominatorOffset];
+    },
+
+    get edges()
+    {
+        return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(this._snapshot, this.rawEdges));
+    },
+
+    get edgesCount()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._edgesCountOffset];
+    },
+
+    get id()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeIdOffset];
+    },
+
+    get instancesCount()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeInstancesCountOffset];
+    },
+
+    get isHidden()
+    {
+        return this._type() === this._snapshot._nodeHiddenType;
+    },
+
+    get isRoot()
+    {
+        return this.nodeIndex === this._snapshot._rootNodeIndex;
+    },
+
+    get name()
+    {
+        return this._snapshot._strings[this._name()];
+    },
+
+    get rawEdges()
+    {
+        var firstEdgeIndex = this._firstEdgeIndex();
+        return new WebInspector.HeapSnapshotArraySlice(this._snapshot, "_nodes", firstEdgeIndex, firstEdgeIndex + this.edgesCount * this._snapshot._edgeFieldsCount);
+    },
+
+    get retainedSize()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeRetainedSizeOffset];
+    },
+
+    get retainers()
+    {
+        return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(this._snapshot, this._snapshot.retainers(this)));
+    },
+
+    get selfSize()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeSelfSizeOffset];
+    },
+
+    get type()
+    {
+        return this._snapshot._nodeTypes[this._type()];
+    },
+
+    _name: function()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeNameOffset];
+    },
+
+    get _nodes()
+    {
+        return this._snapshot._nodes;
+    },
+
+    _firstEdgeIndex: function()
+    {
+        return this.nodeIndex + this._snapshot._firstEdgeOffset;
+    },
+
+    get _nextNodeIndex()
+    {
+        return this._firstEdgeIndex() + this.edgesCount * this._snapshot._edgeFieldsCount;
+    },
+
+    _type: function()
+    {
+        return this._nodes[this.nodeIndex + this._snapshot._nodeTypeOffset];
+    }
+};
+
+WebInspector.HeapSnapshotNodeIterator = function(node)
+{
+    this.node = node;
+}
+
+WebInspector.HeapSnapshotNodeIterator.prototype = {
+    first: function()
+    {
+        this.node.nodeIndex = this.node._firstNodeIndex;
+    },
+
+    hasNext: function()
+    {
+        return this.node.nodeIndex < this.node._nodes.length;
+    },
+
+    get index()
+    {
+        return this.node.nodeIndex;
+    },
+
+    set index(newIndex)
+    {
+        this.node.nodeIndex = newIndex;
+    },
+
+    get item()
+    {
+        return this.node;
+    },
+
+    next: function()
+    {
+        this.node.nodeIndex = this.node._nextNodeIndex;
+    }
+}
+
+WebInspector.HeapSnapshot = function(profile)
+{
+    this._nodes = profile.nodes;
+    this._strings = profile.strings;
+
+    this._init();
+}
+
+WebInspector.HeapSnapshot.prototype = {
+    _init: function()
+    {
+        this._metaNodeIndex = 0;
+        this._rootNodeIndex = 1;
+        var meta = this._nodes[this._metaNodeIndex];
+        this._nodeTypeOffset = meta.fields.indexOf("type");
+        this._nodeNameOffset = meta.fields.indexOf("name");
+        this._nodeIdOffset = meta.fields.indexOf("id");
+        this._nodeInstancesCountOffset = this._nodeIdOffset;
+        this._nodeSelfSizeOffset = meta.fields.indexOf("self_size");
+        this._nodeRetainedSizeOffset = meta.fields.indexOf("retained_size");
+        this._dominatorOffset = meta.fields.indexOf("dominator");
+        this._edgesCountOffset = meta.fields.indexOf("children_count");
+        this._firstEdgeOffset = meta.fields.indexOf("children");
+        this._nodeTypes = meta.types[this._nodeTypeOffset];
+        this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
+        var edgesMeta = meta.types[this._firstEdgeOffset];
+        this._edgeFieldsCount = edgesMeta.fields.length;
+        this._edgeTypeOffset = edgesMeta.fields.indexOf("type");
+        this._edgeNameOffset = edgesMeta.fields.indexOf("name_or_index");
+        this._edgeToNodeOffset = edgesMeta.fields.indexOf("to_node");
+        this._edgeTypes = edgesMeta.types[this._edgeTypeOffset];
+        this._edgeElementType = this._edgeTypes.indexOf("element");
+        this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
+        this._edgeInternalType = this._edgeTypes.indexOf("internal");
+        this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
+    },
+
+    dispose: function()
+    {
+        delete this._nodes;
+        delete this._strings;
+        if (this._idsMap)
+            delete this._idsMap;
+        if (this._retainers) {
+            delete this._retainers;
+            delete this._nodesToRetainers;
+        }
+        if (this._aggregates) {
+            delete this._aggregates;
+            this._aggregatesWithIndexes = false;
+        }
+    },
+
+    get allNodes()
+    {
+        return new WebInspector.HeapSnapshotNodeIterator(this.rootNode);
+    },
+
+    get nodesCount()
+    {
+        if (this._nodesCount)
+            return this._nodesCount;
+
+        this._nodesCount = 0;
+        for (var iter = this.allNodes; iter.hasNext(); iter.next())
+            ++this._nodesCount;
+        return this._nodesCount;
+    },
+
+    restore: function(profile)
+    {
+        this._nodes = profile.nodes;
+        this._strings = profile.strings;
+    },
+
+    get rootNode()
+    {
+        return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
+    },
+
+    get totalSize()
+    {
+        return this.rootNode.retainedSize;
+    },
+
+    get idsMap()
+    {
+        if (this._idsMap)
+            return this._idsMap;
+
+        this._idsMap = [];
+        for (var iter = this.allNodes; iter.hasNext(); iter.next()) {
+            this._idsMap[iter.node.id] = true;
+        }
+        return this._idsMap;
+    },
+
+    retainers: function(node)
+    {
+        if (!this._retainers)
+            this._buildRetainers();
+
+        var retIndexFrom = this._nodesToRetainers[node.nodeIndex];
+        var retIndexTo = this._nodesToRetainers[node._nextNodeIndex];
+        return new WebInspector.HeapSnapshotArraySlice(this, "_retainers", retIndexFrom, retIndexTo);
+    },
+
+    aggregates: function(withNodeIndexes)
+    {
+        if (!this._aggregates)
+            this._buildAggregates();
+        if (withNodeIndexes && !this._aggregatesWithIndexes)
+            this._buildAggregatesIndexes();
+        return this._aggregates;
+    },
+
+    _buildRetainers: function()
+    {
+        this._nodesToRetainers = [];
+        for (var nodesIter = this.allNodes; nodesIter.hasNext(); nodesIter.next()) {
+            var node = nodesIter.node;
+            if (!(node.nodeIndex in this._nodesToRetainers))
+                this._nodesToRetainers[node.nodeIndex] = 0;
+            for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
+                var edge = edgesIter.edge;
+                var nodeIndex = edge.nodeIndex;
+                if (!(nodeIndex in this._nodesToRetainers))
+                    this._nodesToRetainers[nodeIndex] = 0;
+                this._nodesToRetainers[nodeIndex] += this._edgeFieldsCount;
+            }
+        }
+        nodesIter = this.allNodes;
+        var node = nodesIter.node;
+        var prevIndex = this._nodesToRetainers[node.nodeIndex] = 0;
+        var prevRetsCount = this._nodesToRetainers[node.nodeIndex];
+        nodesIter.next();
+        for (; nodesIter.hasNext(); nodesIter.next()) {
+            node = nodesIter.node;
+            var savedRefsCount = this._nodesToRetainers[node.nodeIndex];
+            this._nodesToRetainers[node.nodeIndex] = prevIndex + prevRetsCount;
+            prevIndex = this._nodesToRetainers[node.nodeIndex];
+            prevRetsCount = savedRefsCount;
+        }
+        this._retainers = new Array(prevIndex + prevRetsCount);
+        this._nodesToRetainers[this._nodes.length] = this._retainers.length;
+        for (nodesIter = this.allNodes; nodesIter.hasNext(); nodesIter.next()) {
+            node = nodesIter.node;
+            var retsCount = this._nodesToRetainers[node._nextNodeIndex] - this._nodesToRetainers[node.nodeIndex];
+            if (retsCount > 0) {
+                this._retainers[this._nodesToRetainers[node.nodeIndex]] = retsCount;
+            }
+        }
+        for (nodesIter = this.allNodes; nodesIter.hasNext(); nodesIter.next()) {
+            node = nodesIter.node;
+            for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
+                var edge = edgesIter.edge;
+                var nodeIndex = edge.nodeIndex;
+                var retIndex = this._nodesToRetainers[nodeIndex];
+                this._retainers[retIndex] -= this._edgeFieldsCount;
+                var idx = retIndex + this._retainers[retIndex];
+                this._retainers[idx + this._edgeTypeOffset] = edge._type();
+                this._retainers[idx + this._edgeNameOffset] = edge._nameOrIndex;
+                this._retainers[idx + this._edgeToNodeOffset] = node.nodeIndex;
+            }
+        }
+    },
+
+    _buildAggregates: function()
+    {
+        this._aggregates = {};
+        for (var iter = this.allNodes; iter.hasNext(); iter.next()) {
+            var node = iter.node;
+            var className = node.className;
+            var nameMatters = node.type === "object";
+            if (node.selfSize === 0)
+                continue;
+            if (!(className in this._aggregates))
+                this._aggregates[className] = { count: 0, self: 0, maxRet: 0, type: node.type, name: nameMatters ? node.name : null, idxs: [] };
+            var clss = this._aggregates[className];
+            ++clss.count;
+            clss.self += node.selfSize;
+            if (node.retainedSize > clss.maxRet)
+                clss.maxRet = node.retainedSize;
+        }
+    },
+
+    _buildAggregatesIndexes: function()
+    {
+        for (var iter = this.allNodes; iter.hasNext(); iter.next()) {
+            var node = iter.node;
+            var className = node.className;
+            var clss = this._aggregates[className];
+            if (clss)
+                clss.idxs.push(node.nodeIndex);
+        }
+
+        var nodeA = new WebInspector.HeapSnapshotNode(this);
+        var nodeB = new WebInspector.HeapSnapshotNode(this);
+        for (var clss in this._aggregates)
+            this._aggregates[clss].idxs.sort(
+                function(idxA, idxB) {
+                    nodeA.nodeIndex = idxA;
+                    nodeB.nodeIndex = idxB;
+                    return nodeA.id < nodeB.id ? -1 : 1;
+                });
+
+        this._aggregatesWithIndexes = true;
+    }
+};
+
+WebInspector.HeapSnapshotFilteredOrderedIterator = function(snapshot, iterator, filter)
+{
+    this._snapshot = snapshot;
+    this._filter = filter;
+    this._iterator = iterator;
+    this._iterationOrder = null;
+    this._position = 0;
+    this._lastComparator = null;
+}
+
+WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
+    _createIterationOrder: function()
+    {
+        this._iterationOrder = [];
+        var iterator = this._iterator;
+        if (!this._filter) {
+            for (iterator.first(); iterator.hasNext(); iterator.next())
+                this._iterationOrder.push(iterator.index);
+        } else {
+            for (iterator.first(); iterator.hasNext(); iterator.next()) {
+                if (this._filter(iterator.item))
+                    this._iterationOrder.push(iterator.index);
+            }
+        }
+    },
+
+    first: function()
+    {
+        this._position = 0;
+    },
+
+    hasNext: function()
+    {
+        return this._position < this._iterationOrder.length;
+    },
+
+    get isEmpty()
+    {
+        if (this._iterationOrder)
+            return !this._iterationOrder.length;
+        var iterator = this._iterator;
+        if (!this._filter) {
+            iterator.first();
+            return !iterator.hasNext();
+        }
+        for (iterator.first(); iterator.hasNext(); iterator.next())
+            if (this._filter(iterator.item)) return false;
+        return true;
+    },
+
+    get item()
+    {
+        this._iterator.index = this._iterationOrder[this._position];
+        return this._iterator.item;
+    },
+
+    get lastComparator()
+    {
+        return this._lastComparator;
+    },
+
+    get length()
+    {
+        if (!this._iterationOrder)
+            this._createIterationOrder();
+        return this._iterationOrder.length;
+    },
+
+    next: function()
+    {
+        ++this._position;
+    }
+}
+
+WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = function(fieldNames)
+{
+    return {fieldName1:fieldNames[0], ascending1:fieldNames[1], fieldName2:fieldNames[2], ascending2:fieldNames[3]};
+}
+
+WebInspector.HeapSnapshotEdgesProvider = function(snapshot, rawEdges, filter)
+{
+    WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, rawEdges)), filter);
+}
+
+WebInspector.HeapSnapshotEdgesProvider.prototype = {
+    sort: function(comparator)
+    {
+        if (this._lastComparator === comparator)
+            return false;
+        this._lastComparator = comparator;
+        var fieldName1 = comparator.fieldName1;
+        var fieldName2 = comparator.fieldName2;
+        var ascending1 = comparator.ascending1;
+        var ascending2 = comparator.ascending2;
+
+        var edgeA = this._iterator.item.clone();
+        var edgeB = edgeA.clone();
+        var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
+        var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+
+        function sortByEdgeFieldName(ascending, indexA, indexB)
+        {
+            edgeA.edgeIndex = indexA;
+            edgeB.edgeIndex = indexB;
+            if (edgeB.name === "__proto__") return -1;
+            if (edgeA.name === "__proto__") return 1;
+            var result =
+                edgeA.hasStringName === edgeB.hasStringName ?
+                (edgeA.name < edgeB.name ? -1 : (edgeA.name > edgeB.name ? 1 : 0)) :
+                (edgeA.hasStringName ? -1 : 1);
+            return ascending ? result : -result;
+        }
+
+        function sortByNodeField(fieldName, ascending, indexA, indexB)
+        {
+            edgeA.edgeIndex = indexA;
+            edgeB.edgeIndex = indexB;
+            nodeA.nodeIndex = edgeA.nodeIndex;
+            nodeB.nodeIndex = edgeB.nodeIndex;
+            var valueA = nodeA[fieldName];
+            var valueB = nodeB[fieldName];
+            var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
+            return ascending ? result : -result;
+        }
+
+        if (!this._iterationOrder)
+            this._createIterationOrder();
+
+        function sortByEdgeAndNode(indexA, indexB) {
+            var result = sortByEdgeFieldName(ascending1, indexA, indexB);
+            if (result === 0)
+                result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
+            return result;
+        }
+
+        function sortByNodeAndEdge(indexA, indexB) {
+            var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
+            if (result === 0)
+                result = sortByEdgeFieldName(ascending2, indexA, indexB);
+            return result;
+        }
+
+        function sortByNodeAndNode(indexA, indexB) {
+            var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
+            if (result === 0)
+                result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
+            return result;
+        }
+
+        if (fieldName1 === "!edgeName")
+            this._iterationOrder.sort(sortByEdgeAndNode);
+        else if (fieldName2 === "!edgeName")
+            this._iterationOrder.sort(sortByNodeAndEdge);
+        else
+            this._iterationOrder.sort(sortByNodeAndNode);
+        return true;
+    }
+};
+
+WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;
+
+WebInspector.HeapSnapshotNodesProvider = function(snapshot, nodes, filter)
+{
+    WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, nodes, filter);
+}
+
+WebInspector.HeapSnapshotNodesProvider.prototype = {
+    sort: function(comparator)
+    {
+        if (this._lastComparator === comparator)
+            return false;
+        this._lastComparator = comparator;
+        var fieldName1 = comparator.fieldName1;
+        var fieldName2 = comparator.fieldName2;
+        var ascending1 = comparator.ascending1;
+        var ascending2 = comparator.ascending2;
+
+        var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
+        var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+
+        function sortByNodeField(fieldName, ascending, indexA, indexB)
+        {
+            nodeA.nodeIndex = indexA;
+            nodeB.nodeIndex = indexB;
+            var valueA = nodeA[fieldName];
+            var valueB = nodeB[fieldName];
+            var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
+            return ascending ? result : -result;
+        }
+
+        if (!this._iterationOrder)
+            this._createIterationOrder();
+
+        function sortByComparator(indexA, indexB) {
+            var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
+            if (result === 0)
+                result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
+            return result;
+        }
+
+        this._iterationOrder.sort(sortByComparator);
+        return true;
+    }
+};
+
+WebInspector.HeapSnapshotNodesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;
+
+WebInspector.HeapSnapshotPathFinder = function(snapshot, targetNodeIndex)
+{
+    this._snapshot = snapshot;
+    this._maxLength = 1;
+    this._lengthLimit = 15;
+    this._targetNodeIndex = targetNodeIndex;
+    this._currentPath = null;
+    this._skipHidden = !WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+    this._rootChildren = this._fillRootChildren();
+}
+
+WebInspector.HeapSnapshotPathFinder.prototype = {
+    findNext: function()
+    {
+        for (var i = 0; i < 100000; ++i) {
+            if (!this._buildNextPath()) {
+                if (++this._maxLength >= this._lengthLimit)
+                    return null;
+                this._currentPath = null;
+                if (!this._buildNextPath())
+                    return null;
+            }
+            if (this._isPathFound())
+                return {path:this._pathToString(this._currentPath), len:this._currentPath.length};
+        }
+
+        return false;
+    },
+
+    _fillRootChildren: function()
+    {
+        var result = [];
+        for (var iter = this._snapshot.rootNode.edges; iter.hasNext(); iter.next())
+            result[iter.edge.nodeIndex] = true;
+        return result;
+    },
+
+    _appendToCurrentPath: function(iter)
+    {
+        this._currentPath._cache[this._lastEdge.nodeIndex] = true;
+        this._currentPath.push(iter);
+    },
+
+    _removeLastFromCurrentPath: function()
+    {
+        this._currentPath.pop();
+        delete this._currentPath._cache[this._lastEdge.nodeIndex];
+    },
+
+    _hasInPath: function(nodeIndex)
+    {
+        return this._targetNodeIndex === nodeIndex
+            || !!this._currentPath._cache[nodeIndex];
+    },
+
+    _isPathFound: function()
+    {
+        return this._currentPath.length === this._maxLength
+            && this._lastEdge.nodeIndex in this._rootChildren;
+    },
+
+    get _lastEdgeIter()
+    {
+        return this._currentPath[this._currentPath.length - 1];
+    },
+
+    get _lastEdge()
+    {
+        return this._lastEdgeIter.edge;
+    },
+
+    _skipEdge: function(edge)
+    {
+        return (this._skipHidden && (edge.isHidden || edge.node.isHidden))
+            || this._hasInPath(edge.nodeIndex);
+    },
+
+    _nextEdgeIter: function()
+    {
+        var iter = this._lastEdgeIter;
+        while (this._skipEdge(iter.edge) && iter.hasNext())
+            iter.next();
+        return iter;
+    },
+
+    _buildNextPath: function()
+    {
+        if (this._currentPath !== null) {
+            var iter = this._lastEdgeIter;
+            while (true) {
+                iter.next();
+                if (iter.hasNext())
+                    return true;
+                while (true) {
+                    if (this._currentPath.length > 1) {
+                        this._removeLastFromCurrentPath();
+                        iter = this._lastEdgeIter;
+                        iter.next();
+                        iter = this._nextEdgeIter();
+                        if (iter.hasNext()) {
+                            while (this._currentPath.length < this._maxLength) {
+                                iter = this._nextEdgeIter();
+                                if (iter.hasNext())
+                                    this._appendToCurrentPath(iter.edge.node.retainers);
+                                else
+                                    return true;
+                            }
+                            return true;
+                        }
+                    } else
+                        return false;
+                }
+            }
+        } else {
+            var node = new WebInspector.HeapSnapshotNode(this._snapshot, this._targetNodeIndex);
+            this._currentPath = [node.retainers];
+            this._currentPath._cache = {};
+            while (this._currentPath.length < this._maxLength) {
+                var iter = this._nextEdgeIter();
+                if (iter.hasNext())
+                    this._appendToCurrentPath(iter.edge.node.retainers);
+                else
+                    break;
+            }
+            return true;
+        }
+    },
+
+    _nodeToString: function(node)
+    {
+        if (node.id === 1)
+            return node.name;
+        else
+            return node.name + "@" + node.id;
+    },
+
+    _pathToString: function(path)
+    {
+        if (!path)
+            return "";
+        var sPath = [];
+        for (var j = 0; j < path.length; ++j)
+            sPath.push(path[j].edge.toString());
+        sPath.push(this._nodeToString(path[path.length - 1].edge.node));
+        sPath.reverse();
+        return sPath.join("");
+    }
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshotView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshotView.js
new file mode 100644
index 0000000..44b95c3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HeapSnapshotView.js
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.HeapSnapshotView = function(parent, profile)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("heap-snapshot-view");
+
+    this.parent = parent;
+    this.parent.addEventListener("profile added", this._updateBaseOptions, this);
+
+    this.showCountAsPercent = false;
+    this.showSizeAsPercent = false;
+    this.showCountDeltaAsPercent = false;
+    this.showSizeDeltaAsPercent = false;
+
+    this.categories = {
+        code: new WebInspector.ResourceCategory("code", WebInspector.UIString("Code"), "rgb(255,121,0)"),
+        data: new WebInspector.ResourceCategory("data", WebInspector.UIString("Objects"), "rgb(47,102,236)")
+    };
+
+    var summaryContainer = document.createElement("div");
+    summaryContainer.id = "heap-snapshot-summary-container";
+
+    this.countsSummaryBar = new WebInspector.SummaryBar(this.categories);
+    this.countsSummaryBar.element.className = "heap-snapshot-summary";
+    this.countsSummaryBar.calculator = new WebInspector.HeapSummaryCountCalculator();
+    var countsLabel = document.createElement("div");
+    countsLabel.className = "heap-snapshot-summary-label";
+    countsLabel.textContent = WebInspector.UIString("Count");
+    this.countsSummaryBar.element.appendChild(countsLabel);
+    summaryContainer.appendChild(this.countsSummaryBar.element);
+
+    this.sizesSummaryBar = new WebInspector.SummaryBar(this.categories);
+    this.sizesSummaryBar.element.className = "heap-snapshot-summary";
+    this.sizesSummaryBar.calculator = new WebInspector.HeapSummarySizeCalculator();
+    var sizesLabel = document.createElement("label");
+    sizesLabel.className = "heap-snapshot-summary-label";
+    sizesLabel.textContent = WebInspector.UIString("Size");
+    this.sizesSummaryBar.element.appendChild(sizesLabel);
+    summaryContainer.appendChild(this.sizesSummaryBar.element);
+
+    this.element.appendChild(summaryContainer);
+
+    var columns = {
+        cons: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+        count: { title: WebInspector.UIString("Count"), width: "54px", sortable: true },
+        size: { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true },
+        // \xb1 is a "plus-minus" sign.
+        countDelta: { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true },
+        sizeDelta: { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true }
+    };
+
+    this.dataGrid = new WebInspector.DataGrid(columns);
+    this.dataGrid.addEventListener("sorting changed", this._sortData, this);
+    this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
+    this.element.appendChild(this.dataGrid.element);
+
+    this.profile = profile;
+
+    this.baseSelectElement = document.createElement("select");
+    this.baseSelectElement.className = "status-bar-item";
+    this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
+    this._updateBaseOptions();
+
+    this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
+    this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+
+    this._loadProfile(this.profile, profileCallback.bind(this));
+
+    function profileCallback(profile)
+    {
+        var list = this._profiles();
+        var profileIndex;
+        for (var i = 0; i < list.length; ++i)
+            if (list[i].uid === profile.uid) {
+                profileIndex = i;
+                break;
+            }
+        if (profileIndex > 0)
+            this.baseSelectElement.selectedIndex = profileIndex - 1;
+        else
+            this.baseSelectElement.selectedIndex = profileIndex;
+        this._resetDataGridList(resetCompleted.bind(this));
+    }
+
+    function resetCompleted()
+    {
+        this.refresh();
+        this._updatePercentButton();
+    }
+}
+
+WebInspector.HeapSnapshotView.prototype = {
+    get statusBarItems()
+    {
+        return [this.baseSelectElement, this.percentButton.element];
+    },
+
+    get profile()
+    {
+        return this._profile;
+    },
+
+    set profile(profile)
+    {
+        this._profile = profile;
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this.dataGrid.updateWidths();
+    },
+
+    hide: function()
+    {
+        WebInspector.View.prototype.hide.call(this);
+        this._currentSearchResultIndex = -1;
+    },
+
+    resize: function()
+    {
+        if (this.dataGrid)
+            this.dataGrid.updateWidths();
+    },
+
+    refresh: function()
+    {
+        this.dataGrid.removeChildren();
+
+        var children = this.snapshotDataGridList.children;
+        var count = children.length;
+        for (var index = 0; index < count; ++index)
+            this.dataGrid.appendChild(children[index]);
+
+        this._updateSummaryGraph();
+    },
+
+    refreshShowAsPercents: function()
+    {
+        this._updatePercentButton();
+        this.refreshVisibleData();
+    },
+
+    _deleteSearchMatchedFlags: function(node)
+    {
+        delete node._searchMatchedConsColumn;
+        delete node._searchMatchedCountColumn;
+        delete node._searchMatchedSizeColumn;
+        delete node._searchMatchedCountDeltaColumn;
+        delete node._searchMatchedSizeDeltaColumn;
+    },
+
+    searchCanceled: function()
+    {
+        if (this._searchResults) {
+            for (var i = 0; i < this._searchResults.length; ++i) {
+                var profileNode = this._searchResults[i].profileNode;
+                this._deleteSearchMatchedFlags(profileNode);
+                profileNode.refresh();
+            }
+        }
+
+        delete this._searchFinishedCallback;
+        this._currentSearchResultIndex = -1;
+        this._searchResults = [];
+    },
+
+    performSearch: function(query, finishedCallback)
+    {
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled();
+
+        query = query.trim();
+
+        if (!query.length)
+            return;
+
+        this._searchFinishedCallback = finishedCallback;
+
+        var helper = WebInspector.HeapSnapshotView.SearchHelper;
+
+        var operationAndNumber = helper.parseOperationAndNumber(query);
+        var operation = operationAndNumber[0];
+        var queryNumber = operationAndNumber[1];
+
+        var percentUnits = helper.percents.test(query);
+        var megaBytesUnits = helper.megaBytes.test(query);
+        var kiloBytesUnits = helper.kiloBytes.test(query);
+        var bytesUnits = helper.bytes.test(query);
+
+        var queryNumberBytes = (megaBytesUnits ? (queryNumber * 1024 * 1024) : (kiloBytesUnits ? (queryNumber * 1024) : queryNumber));
+
+        function matchesQuery(heapSnapshotDataGridNode)
+        {
+            WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags(heapSnapshotDataGridNode);
+
+            if (percentUnits) {
+                heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.countPercent, queryNumber);
+                heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.sizePercent, queryNumber);
+                heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDeltaPercent, queryNumber);
+                heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDeltaPercent, queryNumber);
+            } else if (megaBytesUnits || kiloBytesUnits || bytesUnits) {
+                heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.size, queryNumberBytes);
+                heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDelta, queryNumberBytes);
+            } else {
+                heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.count, queryNumber);
+                heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDelta, queryNumber);
+            }
+
+            if (heapSnapshotDataGridNode.constructorName.hasSubstring(query, true))
+                heapSnapshotDataGridNode._searchMatchedConsColumn = true;
+
+            if (heapSnapshotDataGridNode._searchMatchedConsColumn ||
+                heapSnapshotDataGridNode._searchMatchedCountColumn ||
+                heapSnapshotDataGridNode._searchMatchedSizeColumn ||
+                heapSnapshotDataGridNode._searchMatchedCountDeltaColumn ||
+                heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn) {
+                heapSnapshotDataGridNode.refresh();
+                return true;
+            }
+
+            return false;
+        }
+
+        var current = this.snapshotDataGridList.children[0];
+        var depth = 0;
+        var info = {};
+
+        // The second and subsequent levels of heap snapshot nodes represent retainers,
+        // so recursive expansion will be infinite, since a graph is being traversed.
+        // So default to a recursion cap of 2 levels.
+        const maxDepth = 2;
+
+        while (current) {
+            if (matchesQuery(current))
+                this._searchResults.push({ profileNode: current });
+            current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
+            depth += info.depthChange;
+        }
+
+        finishedCallback(this, this._searchResults.length);
+    },
+
+    // FIXME: move these methods to a superclass, inherit both views from it.
+    jumpToFirstSearchResult: WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult,
+    jumpToLastSearchResult: WebInspector.CPUProfileView.prototype.jumpToLastSearchResult,
+    jumpToNextSearchResult: WebInspector.CPUProfileView.prototype.jumpToNextSearchResult,
+    jumpToPreviousSearchResult: WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult,
+    showingFirstSearchResult: WebInspector.CPUProfileView.prototype.showingFirstSearchResult,
+    showingLastSearchResult: WebInspector.CPUProfileView.prototype.showingLastSearchResult,
+    _jumpToSearchResult: WebInspector.CPUProfileView.prototype._jumpToSearchResult,
+
+    refreshVisibleData: function()
+    {
+        var child = this.dataGrid.children[0];
+        while (child) {
+            child.refresh();
+            child = child.traverseNextNode(false, null, true);
+        }
+        this._updateSummaryGraph();
+    },
+
+    _changeBase: function()
+    {
+        if (this.baseSnapshot.uid === this._profiles()[this.baseSelectElement.selectedIndex].uid)
+            return;
+
+        this._resetDataGridList(resetCompleted.bind(this));
+
+        function resetCompleted() {
+            this.refresh();
+
+            if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+                return;
+
+            // The current search needs to be performed again. First negate out previous match
+            // count by calling the search finished callback with a negative number of matches.
+            // Then perform the search again with the same query and callback.
+            this._searchFinishedCallback(this, -this._searchResults.length);
+            this.performSearch(this.currentQuery, this._searchFinishedCallback);
+        }
+    },
+
+    _createSnapshotDataGridList: function()
+    {
+        if (this._snapshotDataGridList)
+          delete this._snapshotDataGridList;
+
+        this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.profile.entries);
+        return this._snapshotDataGridList;
+    },
+
+    _profiles: function()
+    {
+        return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+    },
+
+    _loadProfile: function(profile, callback)
+    {
+        WebInspector.panels.profiles.loadHeapSnapshot(profile.uid, callback);
+    },
+
+    processLoadedSnapshot: function(profile, loadedSnapshot)
+    {
+        var snapshot = WebInspector.HeapSnapshotView.prototype._convertSnapshot(loadedSnapshot);
+        profile.children = snapshot.children;
+        profile.entries = snapshot.entries;
+        profile.lowlevels = snapshot.lowlevels;
+        WebInspector.HeapSnapshotView.prototype._prepareProfile(profile);
+    },
+
+    _mouseDownInDataGrid: function(event)
+    {
+        if (event.detail < 2)
+            return;
+
+        var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+        if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column")))
+            return;
+
+        if (cell.hasStyleClass("count-column"))
+            this.showCountAsPercent = !this.showCountAsPercent;
+        else if (cell.hasStyleClass("size-column"))
+            this.showSizeAsPercent = !this.showSizeAsPercent;
+        else if (cell.hasStyleClass("countDelta-column"))
+            this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent;
+        else if (cell.hasStyleClass("sizeDelta-column"))
+            this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent;
+
+        this.refreshShowAsPercents();
+
+        event.preventDefault();
+        event.stopPropagation();
+    },
+
+    get _isShowingAsPercent()
+    {
+        return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent;
+    },
+
+    _percentClicked: function(event)
+    {
+        var currentState = this._isShowingAsPercent;
+        this.showCountAsPercent = !currentState;
+        this.showSizeAsPercent = !currentState;
+        this.showCountDeltaAsPercent = !currentState;
+        this.showSizeDeltaAsPercent = !currentState;
+        this.refreshShowAsPercents();
+    },
+
+    _convertSnapshot: function(loadedSnapshot)
+    {
+        var snapshot = new WebInspector.HeapSnapshot(loadedSnapshot);
+        var result = {lowlevels: {}, entries: {}, children: {}};
+        var rootEdgesIter = snapshot.rootNode.edges;
+        for (var iter = rootEdgesIter; iter.hasNext(); iter.next()) {
+            var node = iter.edge.node;
+            if (node.isHidden)
+                result.lowlevels[node.name] = {count: node.instancesCount, size: node.selfSize, type: node.name};
+            else if (node.instancesCount)
+                result.entries[node.name] = {constructorName: node.name, count: node.instancesCount, size: node.selfSize};
+            else {
+                var entry = {constructorName: node.name};
+                for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
+                    var edge = innerIter.edge;
+                    entry[edge.nodeIndex] = {constructorName: edge.node.name, count: edge.name};
+                }
+                result.children[rootEdgesIter.edge.nodeIndex] = entry;
+            }
+        }
+        return result;
+    },
+
+    _prepareProfile: function(profile)
+    {
+        for (var profileEntry in profile.entries)
+            profile.entries[profileEntry].retainers = {};
+        profile.clusters = {};
+
+        for (var addr in profile.children) {
+            var retainer = profile.children[addr];
+            var retainerId = retainer.constructorName + ":" + addr;
+            for (var childAddr in retainer) {
+                if (childAddr === "constructorName") continue;
+                var item = retainer[childAddr];
+                var itemId = item.constructorName + ":" + childAddr;
+                if ((item.constructorName === "Object" || item.constructorName === "Array")) {
+                    if (!(itemId in profile.clusters))
+                        profile.clusters[itemId] = { constructorName: itemId, retainers: {} };
+                    mergeRetainers(profile.clusters[itemId], item);
+                }
+                mergeRetainers(profile.entries[item.constructorName], item);
+            }
+        }
+
+        function mergeRetainers(entry, item)
+        {
+            if (!(retainer.constructorName in entry.retainers))
+               entry.retainers[retainer.constructorName] = { constructorName: retainer.constructorName, count: 0, clusters: {} };
+            var retainerEntry = entry.retainers[retainer.constructorName];
+            retainerEntry.count += item.count;
+            if (retainer.constructorName === "Object" || retainer.constructorName === "Array")
+                retainerEntry.clusters[retainerId] = true;
+        }
+    },
+
+    _resetDataGridList: function(callback)
+    {
+        this._loadProfile(this._profiles()[this.baseSelectElement.selectedIndex], profileLoaded.bind(this));
+
+        function profileLoaded(profile)
+        {
+            this.baseSnapshot = profile;
+            var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("size", false);
+            if (this.snapshotDataGridList)
+                lastComparator = this.snapshotDataGridList.lastComparator;
+            this.snapshotDataGridList = this._createSnapshotDataGridList();
+            this.snapshotDataGridList.sort(lastComparator, true);
+            callback();
+        }
+    },
+
+    _sortData: function()
+    {
+        var sortAscending = this.dataGrid.sortOrder === "ascending";
+        var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+        var sortProperty = {
+            cons: ["constructorName", null],
+            count: ["count", "constructorName"],
+            size: ["size", "constructorName"],
+            countDelta: [this.showCountDeltaAsPercent ? "countDeltaPercent" : "countDelta", "constructorName"],
+            sizeDelta: [this.showSizeDeltaAsPercent ? "sizeDeltaPercent" : "sizeDelta", "constructorName"]
+        }[sortColumnIdentifier];
+
+        this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty[0], sortProperty[1], sortAscending));
+
+        this.refresh();
+    },
+
+    _updateBaseOptions: function()
+    {
+        var list = this._profiles();
+        // We're assuming that snapshots can only be added.
+        if (this.baseSelectElement.length === list.length)
+            return;
+
+        for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
+            var baseOption = document.createElement("option");
+            var title = list[i].title;
+            if (!title.indexOf(UserInitiatedProfileName))
+                title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
+            baseOption.label = WebInspector.UIString("Compared to %s", title);
+            this.baseSelectElement.appendChild(baseOption);
+        }
+    },
+
+    _updatePercentButton: function()
+    {
+        if (this._isShowingAsPercent) {
+            this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
+            this.percentButton.toggled = true;
+        } else {
+            this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
+            this.percentButton.toggled = false;
+        }
+    },
+
+    _updateSummaryGraph: function()
+    {
+        this.countsSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
+        this.countsSummaryBar.update(this.profile.lowlevels);
+
+        this.sizesSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
+        this.sizesSummaryBar.update(this.profile.lowlevels);
+    }
+};
+
+WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.HeapSnapshotView.SearchHelper = {
+    // In comparators, we assume that a value from a node is passed as the first parameter.
+    operations: {
+        LESS: function (a, b) { return a !== null && a < b; },
+        LESS_OR_EQUAL: function (a, b) { return a !== null && a <= b; },
+        EQUAL: function (a, b) { return a !== null && a === b; },
+        GREATER_OR_EQUAL: function (a, b) { return a !== null && a >= b; },
+        GREATER: function (a, b) { return a !== null && a > b; }
+    },
+
+    operationParsers: {
+        LESS: /^<(\d+)/,
+        LESS_OR_EQUAL: /^<=(\d+)/,
+        GREATER_OR_EQUAL: /^>=(\d+)/,
+        GREATER: /^>(\d+)/
+    },
+
+    parseOperationAndNumber: function(query)
+    {
+        var operations = WebInspector.HeapSnapshotView.SearchHelper.operations;
+        var parsers = WebInspector.HeapSnapshotView.SearchHelper.operationParsers;
+        for (var operation in parsers) {
+            var match = query.match(parsers[operation]);
+            if (match !== null)
+                return [operations[operation], parseFloat(match[1])];
+        }
+        return [operations.EQUAL, parseFloat(query)];
+    },
+
+    percents: /%$/,
+
+    megaBytes: /MB$/i,
+
+    kiloBytes: /KB$/i,
+
+    bytes: /B$/i
+}
+
+WebInspector.HeapSummaryCalculator = function(lowLevelField)
+{
+    this.total = 1;
+    this.lowLevelField = lowLevelField;
+}
+
+WebInspector.HeapSummaryCalculator.prototype = {
+    computeSummaryValues: function(lowLevels)
+    {
+        var highLevels = { data: 0, code: 0 };
+        this.total = 0;
+        for (var item in lowLevels) {
+            var highItem = this._highFromLow(item);
+            if (highItem) {
+                var value = lowLevels[item][this.lowLevelField];
+                highLevels[highItem] += value;
+                this.total += value;
+            }
+        }
+        var result = { categoryValues: highLevels };
+        if (!this.showAsPercent)
+            result.total = this.total;
+        return result;
+    },
+
+    formatValue: function(value)
+    {
+        if (this.showAsPercent)
+            return WebInspector.UIString("%.2f%%", value / this.total * 100.0);
+        else
+            return this._valueToString(value);
+    },
+
+    get showAsPercent()
+    {
+        return this._showAsPercent;
+    },
+
+    set showAsPercent(x)
+    {
+        this._showAsPercent = x;
+    }
+}
+
+WebInspector.HeapSummaryCountCalculator = function()
+{
+    WebInspector.HeapSummaryCalculator.call(this, "count");
+}
+
+WebInspector.HeapSummaryCountCalculator.prototype = {
+    _highFromLow: function(type)
+    {
+        if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE") return "code";
+        if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/)) return "data";
+        return null;
+    },
+
+    _valueToString: function(value)
+    {
+        return value.toString();
+    }
+}
+
+WebInspector.HeapSummaryCountCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;
+
+WebInspector.HeapSummarySizeCalculator = function()
+{
+    WebInspector.HeapSummaryCalculator.call(this, "size");
+}
+
+WebInspector.HeapSummarySizeCalculator.prototype = {
+    _highFromLow: function(type)
+    {
+        if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE")
+            return "code";
+        if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/) || type.match(/_ARRAY_TYPE$/))
+            return "data";
+        return null;
+    },
+
+    _valueToString: Number.bytesToString
+}
+
+WebInspector.HeapSummarySizeCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers = function(owningTree)
+{
+    this.tree = owningTree;
+
+    WebInspector.DataGridNode.call(this, null, this._hasRetainers);
+
+    this.addEventListener("populate", this._populate, this);
+};
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype = {
+    isEmptySet: function(set)
+    {
+        for (var x in set)
+            return false;
+        return true;
+    },
+
+    get _hasRetainers()
+    {
+        return !this.isEmptySet(this.retainers);
+    },
+
+    get _parent()
+    {
+        // For top-level nodes, return owning tree as a parent, not data grid.
+        return this.parent !== this.dataGrid ? this.parent : this.tree;
+    },
+
+    _populate: function(event)
+    {
+        function appendDiffEntry(baseItem, snapshotItem)
+        {
+            this.appendChild(new WebInspector.HeapSnapshotDataGridRetainerNode(this.snapshotView, baseItem, snapshotItem, this.tree));
+        }
+
+        this.produceDiff(this.baseRetainers, this.retainers, appendDiffEntry.bind(this));
+
+        if (this._parent) {
+            var currentComparator = this._parent.lastComparator;
+            if (currentComparator)
+                this.sort(currentComparator, true);
+        }
+
+        this.removeEventListener("populate", this._populate, this);
+    },
+
+    produceDiff: function(baseEntries, currentEntries, callback)
+    {
+        for (var item in currentEntries)
+            callback(baseEntries[item], currentEntries[item]);
+
+        for (item in baseEntries) {
+            if (!(item in currentEntries))
+                callback(baseEntries[item], null);
+        }
+    },
+
+    sort: function(comparator, force) {
+        if (!force && this.lastComparator === comparator)
+            return;
+
+        this.children.sort(comparator);
+        var childCount = this.children.length;
+        for (var childIndex = 0; childIndex < childCount; ++childIndex)
+            this.children[childIndex]._recalculateSiblings(childIndex);
+        for (var i = 0; i < this.children.length; ++i) {
+            var child = this.children[i];
+            if (!force && (!child.expanded || child.lastComparator === comparator))
+                continue;
+            child.sort(comparator, force);
+        }
+        this.lastComparator = comparator;
+    },
+
+    signForDelta: function(delta) {
+        if (delta === 0)
+            return "";
+        if (delta > 0)
+            return "+";
+        else
+            return "\u2212";  // Math minus sign, same width as plus.
+    },
+
+    showDeltaAsPercent: function(value)
+    {
+        if (value === Number.POSITIVE_INFINITY)
+            return WebInspector.UIString("new");
+        else if (value === Number.NEGATIVE_INFINITY)
+            return WebInspector.UIString("deleted");
+        if (value > 1000.0)
+            return WebInspector.UIString("%s >1000%%", this.signForDelta(value));
+        return WebInspector.UIString("%s%.2f%%", this.signForDelta(value), Math.abs(value));
+    },
+
+    getTotalCount: function()
+    {
+        if (!this._count) {
+            this._count = 0;
+            for (var i = 0, n = this.children.length; i < n; ++i)
+                this._count += this.children[i].count;
+        }
+        return this._count;
+    },
+
+    getTotalSize: function()
+    {
+        if (!this._size) {
+            this._size = 0;
+            for (var i = 0, n = this.children.length; i < n; ++i)
+                this._size += this.children[i].size;
+        }
+        return this._size;
+    },
+
+    get countPercent()
+    {
+        return this.count / this._parent.getTotalCount() * 100.0;
+    },
+
+    get sizePercent()
+    {
+        return this.size / this._parent.getTotalSize() * 100.0;
+    },
+
+    get countDeltaPercent()
+    {
+        if (this.baseCount > 0) {
+            if (this.count > 0)
+                return this.countDelta / this.baseCount * 100.0;
+            else
+                return Number.NEGATIVE_INFINITY;
+        } else
+            return Number.POSITIVE_INFINITY;
+    },
+
+    get sizeDeltaPercent()
+    {
+        if (this.baseSize > 0) {
+            if (this.size > 0)
+                return this.sizeDelta / this.baseSize * 100.0;
+            else
+                return Number.NEGATIVE_INFINITY;
+        } else
+            return Number.POSITIVE_INFINITY;
+    },
+
+    get data()
+    {
+        var data = {};
+
+        data["cons"] = this.constructorName;
+
+        if (this.snapshotView.showCountAsPercent)
+            data["count"] = WebInspector.UIString("%.2f%%", this.countPercent);
+        else
+            data["count"] = this.count;
+
+        if (this.size !== null) {
+            if (this.snapshotView.showSizeAsPercent)
+                data["size"] = WebInspector.UIString("%.2f%%", this.sizePercent);
+            else
+                data["size"] = Number.bytesToString(this.size);
+        } else
+            data["size"] = "";
+
+        if (this.snapshotView.showCountDeltaAsPercent)
+            data["countDelta"] = this.showDeltaAsPercent(this.countDeltaPercent);
+        else
+            data["countDelta"] = WebInspector.UIString("%s%d", this.signForDelta(this.countDelta), Math.abs(this.countDelta));
+
+        if (this.sizeDelta !== null) {
+            if (this.snapshotView.showSizeDeltaAsPercent)
+                data["sizeDelta"] = this.showDeltaAsPercent(this.sizeDeltaPercent);
+            else
+                data["sizeDelta"] = WebInspector.UIString("%s%s", this.signForDelta(this.sizeDelta), Number.bytesToString(Math.abs(this.sizeDelta)));
+        } else
+            data["sizeDelta"] = "";
+
+        return data;
+    },
+
+    createCell: function(columnIdentifier)
+    {
+        var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+
+        if ((columnIdentifier === "cons" && this._searchMatchedConsColumn) ||
+            (columnIdentifier === "count" && this._searchMatchedCountColumn) ||
+            (columnIdentifier === "size" && this._searchMatchedSizeColumn) ||
+            (columnIdentifier === "countDelta" && this._searchMatchedCountDeltaColumn) ||
+            (columnIdentifier === "sizeDelta" && this._searchMatchedSizeDeltaColumn))
+            cell.addStyleClass("highlight");
+
+        return cell;
+    }
+};
+
+WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
+{
+    this.snapshotView = snapshotView;
+
+    if (!snapshotEntry)
+        snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, size: 0, retainers: {} };
+    this.constructorName = snapshotEntry.constructorName;
+    this.count = snapshotEntry.count;
+    this.size = snapshotEntry.size;
+    this.retainers = snapshotEntry.retainers;
+
+    if (!baseEntry)
+        baseEntry = { count: 0, size: 0, retainers: {} };
+    this.baseCount = baseEntry.count;
+    this.countDelta = this.count - this.baseCount;
+    this.baseSize = baseEntry.size;
+    this.sizeDelta = this.size - this.baseSize;
+    this.baseRetainers = baseEntry.retainers;
+
+    WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
+};
+
+WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;
+
+WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries)
+{
+    this.tree = this;
+    this.snapshotView = snapshotView;
+    this.children = [];
+    this.lastComparator = null;
+    this.populateChildren(baseEntries, snapshotEntries);
+};
+
+WebInspector.HeapSnapshotDataGridList.prototype = {
+    appendChild: function(child)
+    {
+        this.insertChild(child, this.children.length);
+    },
+
+    insertChild: function(child, index)
+    {
+        this.children.splice(index, 0, child);
+    },
+
+    removeChildren: function()
+    {
+        this.children = [];
+    },
+
+    populateChildren: function(baseEntries, snapshotEntries)
+    {
+        function appendListEntry(baseItem, snapshotItem)
+        {
+            this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseItem, snapshotItem, this));
+        }
+        this.produceDiff(baseEntries, snapshotEntries, appendListEntry.bind(this));
+    },
+
+    produceDiff: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff,
+    sort: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort,
+    getTotalCount: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount,
+    getTotalSize: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize
+};
+
+WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}];
+
+WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, property2, isAscending)
+{
+    var propertyHash = property + "#" + property2;
+    var comparator = this.propertyComparators[(isAscending ? 1 : 0)][propertyHash];
+    if (!comparator) {
+        comparator = function(lhs, rhs) {
+            var l = lhs[property], r = rhs[property];
+            var result = 0;
+            if (l !== null && r !== null) {
+                result = l < r ? -1 : (l > r ? 1 : 0);
+            }
+            if (result !== 0 || property2 === null) {
+                return isAscending ? result : -result;
+            } else {
+                l = lhs[property2];
+                r = rhs[property2];
+                return l < r ? -1 : (l > r ? 1 : 0);
+            }
+        };
+        this.propertyComparators[(isAscending ? 1 : 0)][propertyHash] = comparator;
+    }
+    return comparator;
+};
+
+WebInspector.HeapSnapshotDataGridRetainerNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
+{
+    this.snapshotView = snapshotView;
+
+    if (!snapshotEntry)
+        snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, clusters: {} };
+    this.constructorName = snapshotEntry.constructorName;
+    this.count = snapshotEntry.count;
+    this.retainers = this._calculateRetainers(this.snapshotView.profile, snapshotEntry.clusters);
+
+    if (!baseEntry)
+        baseEntry = { count: 0, clusters: {} };
+    this.baseCount = baseEntry.count;
+    this.countDelta = this.count - this.baseCount;
+    this.baseRetainers = this._calculateRetainers(this.snapshotView.baseSnapshot, baseEntry.clusters);
+
+    this.size = null;
+    this.sizeDelta = null;
+
+    WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
+}
+
+WebInspector.HeapSnapshotDataGridRetainerNode.prototype = {
+    get sizePercent()
+    {
+        return null;
+    },
+
+    get sizeDeltaPercent()
+    {
+        return null;
+    },
+
+    _calculateRetainers: function(snapshot, clusters)
+    {
+        var retainers = {};
+        if (this.isEmptySet(clusters)) {
+            if (this.constructorName in snapshot.entries)
+                return snapshot.entries[this.constructorName].retainers;
+        } else {
+            // In case when an entry is retained by clusters, we need to gather up the list
+            // of retainers by merging retainers of every cluster.
+            // E.g. having such a tree:
+            //   A
+            //     Object:1  10
+            //       X       3
+            //       Y       4
+            //     Object:2  5
+            //       X       6
+            //
+            // will result in a following retainers list: X 9, Y 4.
+            for (var clusterName in clusters) {
+                if (clusterName in snapshot.clusters) {
+                    var clusterRetainers = snapshot.clusters[clusterName].retainers;
+                    for (var clusterRetainer in clusterRetainers) {
+                        var clusterRetainerEntry = clusterRetainers[clusterRetainer];
+                        if (!(clusterRetainer in retainers))
+                            retainers[clusterRetainer] = { constructorName: clusterRetainerEntry.constructorName, count: 0, clusters: {} };
+                        retainers[clusterRetainer].count += clusterRetainerEntry.count;
+                        for (var clusterRetainerCluster in clusterRetainerEntry.clusters)
+                            retainers[clusterRetainer].clusters[clusterRetainerCluster] = true;
+                    }
+                }
+            }
+        }
+        return retainers;
+    }
+};
+
+WebInspector.HeapSnapshotDataGridRetainerNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;
+
+
+WebInspector.HeapSnapshotProfileType = function()
+{
+    WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
+}
+
+WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";
+
+WebInspector.HeapSnapshotProfileType.prototype = {
+    get buttonTooltip()
+    {
+        return WebInspector.UIString("Take heap snapshot.");
+    },
+
+    get buttonStyle()
+    {
+        return "heap-snapshot-status-bar-item status-bar-item";
+    },
+
+    buttonClicked: function()
+    {
+        InspectorBackend.takeHeapSnapshot(false);
+    },
+
+    get welcomeMessage()
+    {
+        return WebInspector.UIString("Get a heap snapshot by pressing the %s button on the status bar.");
+    },
+
+    createSidebarTreeElementForProfile: function(profile)
+    {
+        return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
+    },
+
+    createView: function(profile)
+    {
+        return new WebInspector.HeapSnapshotView(WebInspector.panels.profiles, profile);
+    }
+}
+
+WebInspector.HeapSnapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/HelpScreen.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HelpScreen.js
new file mode 100644
index 0000000..a1bbf1e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/HelpScreen.js
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.HelpScreen = function(title)
+{
+    this._element = document.createElement("div");
+    this._element.className = "help-window-outer";
+    this._element.addEventListener("keydown", this._onKeyDown.bind(this), false);
+
+    var mainWindow = this._element.createChild("div", "help-window-main");
+    var captionWindow = mainWindow.createChild("div", "help-window-caption");
+    var closeButton = captionWindow.createChild("button", "help-close-button");
+    this.contentElement = mainWindow.createChild("div", "help-content");
+    this.contentElement.tabIndex = 0;
+    this.contentElement.addEventListener("blur", this._onBlur.bind(this), false);
+    captionWindow.createChild("h1", "help-window-title").innerText = title;
+
+    closeButton.innerText = "\u2716"; // Code stands for HEAVY MULTIPLICATION X.
+    closeButton.addEventListener("click", this._hide.bind(this), false);
+    this._closeKeys = [
+        WebInspector.KeyboardShortcut.Keys.Enter.code,
+        WebInspector.KeyboardShortcut.Keys.Esc.code,
+        WebInspector.KeyboardShortcut.Keys.Space.code,
+    ];
+    document.body.appendChild(this._element);
+}
+
+WebInspector.HelpScreen.prototype = {
+    show: function()
+    {
+        if (this._isShown)
+            return;
+
+        this._element.style.visibility = "visible";
+        this._isShown = true;
+        this._previousFocusElement = WebInspector.currentFocusElement;
+        WebInspector.currentFocusElement = this.contentElement;
+    },
+
+    _hide: function()
+    {
+        this._isShown = false;
+        this._element.style.visibility = "hidden";
+        WebInspector.currentFocusElement = this._previousFocusElement;
+    },
+
+    _onKeyDown: function(event)
+    {
+        if (this._isShown && this._closeKeys.indexOf(event.keyCode) >= 0) {
+            this._hide();
+            event.stopPropagation();
+        }
+    },
+
+    _onBlur: function()
+    {
+         // Pretend we're modal, grab focus back if we're still shown.
+        if (this._isShown)
+            WebInspector.currentFocusElement = this.contentElement;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ImageView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ImageView.js
new file mode 100644
index 0000000..917a9da
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ImageView.js
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ImageView = function(resource)
+{
+    WebInspector.ResourceView.call(this, resource);
+
+    this.element.addStyleClass("image");
+}
+
+WebInspector.ImageView.prototype = {
+    hasContent: function()
+    {
+        return true;
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.ResourceView.prototype.show.call(this, parentElement);
+        this._createContentIfNeeded();
+    },
+
+    _createContentIfNeeded: function()
+    {
+        if (this._container)
+            return;
+
+        var imageContainer = document.createElement("div");
+        imageContainer.className = "image";
+        this.element.appendChild(imageContainer);
+
+        var imagePreviewElement = document.createElement("img");
+        imagePreviewElement.addStyleClass("resource-image-view");
+        imageContainer.appendChild(imagePreviewElement);
+
+        this._container = document.createElement("div");
+        this._container.className = "info";
+        this.element.appendChild(this._container);
+
+        var imageNameElement = document.createElement("h1");
+        imageNameElement.className = "title";
+        imageNameElement.textContent = this.resource.displayName;
+        this._container.appendChild(imageNameElement);
+
+        var infoListElement = document.createElement("dl");
+        infoListElement.className = "infoList";
+
+        this.resource.populateImageSource(imagePreviewElement);
+
+        function onImageLoad()
+        {
+            var content = this.resource.content;
+            if (content)
+                var resourceSize = this._base64ToSize(content);
+            else
+                var resourceSize = this.resource.resourceSize;
+
+            var imageProperties = [
+                { name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", imagePreviewElement.naturalWidth, imagePreviewElement.naturalHeight) },
+                { name: WebInspector.UIString("File size"), value: Number.bytesToString(resourceSize) },
+                { name: WebInspector.UIString("MIME type"), value: this.resource.mimeType }
+            ];
+    
+            infoListElement.removeChildren();
+            for (var i = 0; i < imageProperties.length; ++i) {
+                var dt = document.createElement("dt");
+                dt.textContent = imageProperties[i].name;
+                infoListElement.appendChild(dt);
+                var dd = document.createElement("dd");
+                dd.textContent = imageProperties[i].value;
+                infoListElement.appendChild(dd);
+            }
+            var dt = document.createElement("dt");
+            dt.textContent = WebInspector.UIString("URL");
+            infoListElement.appendChild(dt);
+            var dd = document.createElement("dd");
+            dd.appendChild(WebInspector.linkifyURLAsNode(this.resource.url));
+            infoListElement.appendChild(dd);
+
+            this._container.appendChild(infoListElement);
+        }
+        imagePreviewElement.addEventListener("load", onImageLoad.bind(this), false);
+    },
+
+    _base64ToSize: function(content)
+    {
+        if (!content.length)
+            return 0;
+        var size = (content.length || 0) * 3 / 4;
+        if (content.length > 0 && content[content.length - 1] === "=")
+            size--;
+        if (content.length > 1 && content[content.length - 2] === "=")
+            size--;
+        return size;
+    }
+}
+
+WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/applicationCache.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/applicationCache.png
new file mode 100644
index 0000000..50bad87
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/applicationCache.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/auditsIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/auditsIcon.png
new file mode 100644
index 0000000..ebeafdc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/auditsIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/back.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/back.png
new file mode 100644
index 0000000..9363960
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/back.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointBorder.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointBorder.png
new file mode 100644
index 0000000..0b1b550
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointBorder.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalBorder.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalBorder.png
new file mode 100644
index 0000000..430e37e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalBorder.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalCounterBorder.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalCounterBorder.png
new file mode 100644
index 0000000..b4a5030
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointConditionalCounterBorder.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointCounterBorder.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointCounterBorder.png
new file mode 100644
index 0000000..8b77b61
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointCounterBorder.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsActivateButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsActivateButtonGlyph.png
new file mode 100644
index 0000000..ce49aac
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsActivateButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsDeactivateButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsDeactivateButtonGlyph.png
new file mode 100644
index 0000000..5c5fcf6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/breakpointsDeactivateButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/checker.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/checker.png
new file mode 100644
index 0000000..8349908
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/checker.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png
new file mode 100644
index 0000000..b1f9465
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/closeButtons.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/closeButtons.png
new file mode 100644
index 0000000..28158a4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/closeButtons.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleButtonGlyph.png
new file mode 100644
index 0000000..d10d43c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleIcon.png
new file mode 100644
index 0000000..94ffa95
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/consoleIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/cookie.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/cookie.png
new file mode 100644
index 0000000..90c3c15
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/cookie.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/database.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/database.png
new file mode 100644
index 0000000..339efa6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/database.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/databaseTable.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/databaseTable.png
new file mode 100644
index 0000000..3718708
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/databaseTable.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerContinue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerContinue.png
new file mode 100644
index 0000000..d90a855
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerContinue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerPause.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerPause.png
new file mode 100644
index 0000000..97f958a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerPause.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepInto.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepInto.png
new file mode 100644
index 0000000..277f126
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepInto.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOut.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOut.png
new file mode 100644
index 0000000..3032e32
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOut.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOver.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOver.png
new file mode 100644
index 0000000..7d47245
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/debuggerStepOver.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDown.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDown.png
new file mode 100644
index 0000000..cffc835
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDown.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownBlack.png
new file mode 100644
index 0000000..4b49c13
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownWhite.png
new file mode 100644
index 0000000..aebae12
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallDownWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRight.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRight.png
new file mode 100644
index 0000000..a3102ea
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRight.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightBlack.png
new file mode 100644
index 0000000..2c45859
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDown.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDown.png
new file mode 100644
index 0000000..035c069
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDown.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownBlack.png
new file mode 100644
index 0000000..86f67bd
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownWhite.png
new file mode 100644
index 0000000..972d794
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightDownWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightWhite.png
new file mode 100644
index 0000000..a10168f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/disclosureTriangleSmallRightWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/dockButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/dockButtonGlyph.png
new file mode 100644
index 0000000..7052f4b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/dockButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/elementsIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/elementsIcon.png
new file mode 100644
index 0000000..fde3db9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/elementsIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png
new file mode 100644
index 0000000..85e0bd6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png
new file mode 100644
index 0000000..25b2e96
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorIcon.png
new file mode 100644
index 0000000..c697263
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorMediumIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorMediumIcon.png
new file mode 100644
index 0000000..6ca32bb
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorMediumIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorRedDot.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorRedDot.png
new file mode 100644
index 0000000..6f0b164
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/errorRedDot.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/excludeButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/excludeButtonGlyph.png
new file mode 100644
index 0000000..5128576
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/excludeButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/focusButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/focusButtonGlyph.png
new file mode 100644
index 0000000..b71807c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/focusButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/forward.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/forward.png
new file mode 100644
index 0000000..ad70f3e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/forward.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/frame.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/frame.png
new file mode 100644
index 0000000..0d1953c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/frame.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/gearButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/gearButtonGlyph.png
new file mode 100644
index 0000000..19659c9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/gearButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeader.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeader.png
new file mode 100644
index 0000000..6cbefb7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeader.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderPressed.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderPressed.png
new file mode 100644
index 0000000..1153506
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderPressed.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelected.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelected.png
new file mode 100644
index 0000000..71d5af6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelected.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelectedPressed.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelectedPressed.png
new file mode 100644
index 0000000..7047dbe
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/glossyHeaderSelectedPressed.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/goArrow.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/goArrow.png
new file mode 100644
index 0000000..f318a56
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/goArrow.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutLeft.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutLeft.png
new file mode 100644
index 0000000..6426dbd
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutLeft.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutRight.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutRight.png
new file mode 100644
index 0000000..8c87eae
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/graphLabelCalloutRight.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png
new file mode 100644
index 0000000..71256d6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/localStorage.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/localStorage.png
new file mode 100644
index 0000000..44a3019
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/localStorage.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/networkIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/networkIcon.png
new file mode 100644
index 0000000..ba10bba
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/networkIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png
new file mode 100644
index 0000000..faf5df2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneAddButtons.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneAddButtons.png
new file mode 100644
index 0000000..f1c0047
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneAddButtons.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrow.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrow.png
new file mode 100644
index 0000000..d55b865
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrow.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrowActive.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrowActive.png
new file mode 100644
index 0000000..ef3f259
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneBottomGrowActive.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneGrowHandleLine.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneGrowHandleLine.png
new file mode 100644
index 0000000..4eaf61b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneGrowHandleLine.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneSettingsButtons.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneSettingsButtons.png
new file mode 100644
index 0000000..36a6244
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/paneSettingsButtons.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png
new file mode 100644
index 0000000..c3cec5f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/percentButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/percentButtonGlyph.png
new file mode 100644
index 0000000..0ace3b7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/percentButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverArrows.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverArrows.png
new file mode 100644
index 0000000..ccefa16
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverArrows.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverBackground.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverBackground.png
new file mode 100644
index 0000000..f20c988
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/popoverBackground.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileGroupIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileGroupIcon.png
new file mode 100644
index 0000000..44616d4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileGroupIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileIcon.png
new file mode 100644
index 0000000..8008f9b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileSmallIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileSmallIcon.png
new file mode 100644
index 0000000..7935520
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profileSmallIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesIcon.png
new file mode 100644
index 0000000..ecd5b04
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesSilhouette.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesSilhouette.png
new file mode 100644
index 0000000..42bb966
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/profilesSilhouette.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/programCounterBorder.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/programCounterBorder.png
new file mode 100644
index 0000000..fed2f3e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/programCounterBorder.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/radioDot.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/radioDot.png
new file mode 100644
index 0000000..609878f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/radioDot.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordButtonGlyph.png
new file mode 100644
index 0000000..bfdad1a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png
new file mode 100644
index 0000000..2c22f87
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/reloadButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/reloadButtonGlyph.png
new file mode 100644
index 0000000..28e047a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/reloadButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceCSSIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceCSSIcon.png
new file mode 100644
index 0000000..aead6a7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceCSSIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIcon.png
new file mode 100644
index 0000000..1683a09
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIconSmall.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIconSmall.png
new file mode 100644
index 0000000..468ced9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceDocumentIconSmall.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceJSIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceJSIcon.png
new file mode 100644
index 0000000..9ef6ed0
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourceJSIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIcon.png
new file mode 100644
index 0000000..0ed37b6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIconSmall.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIconSmall.png
new file mode 100644
index 0000000..0fa967d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcePlainIconSmall.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesIcon.png
new file mode 100644
index 0000000..982424d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesSizeGraphIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesSizeGraphIcon.png
new file mode 100644
index 0000000..e60dbe5
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesSizeGraphIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesTimeGraphIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesTimeGraphIcon.png
new file mode 100644
index 0000000..c6953e9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/resourcesTimeGraphIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsIcon.png
new file mode 100644
index 0000000..213b31e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsSilhouette.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsSilhouette.png
new file mode 100644
index 0000000..206396f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/scriptsSilhouette.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBlue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBlue.png
new file mode 100644
index 0000000..9c990f4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBlue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBrightBlue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBrightBlue.png
new file mode 100644
index 0000000..b1d8055
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallBrightBlue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallGray.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallGray.png
new file mode 100644
index 0000000..4f3c068
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallGray.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallWhite.png
new file mode 100644
index 0000000..85f430d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/searchSmallWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segment.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segment.png
new file mode 100644
index 0000000..759266e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segment.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentEnd.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentEnd.png
new file mode 100644
index 0000000..72672ff
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentEnd.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHover.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHover.png
new file mode 100644
index 0000000..c5017f4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHover.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHoverEnd.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHoverEnd.png
new file mode 100644
index 0000000..d51363d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentHoverEnd.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelected.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelected.png
new file mode 100644
index 0000000..c92f584
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelected.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelectedEnd.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelectedEnd.png
new file mode 100644
index 0000000..be5e085
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/segmentSelectedEnd.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/sessionStorage.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/sessionStorage.png
new file mode 100644
index 0000000..4d50e35
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/sessionStorage.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/spinner.gif b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/spinner.gif
new file mode 100644
index 0000000..5f68c02
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/spinner.gif
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDimple.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDimple.png
new file mode 100644
index 0000000..584ffd4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDimple.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDividerBackground.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDividerBackground.png
new file mode 100644
index 0000000..1120a7f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/splitviewDividerBackground.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBackground.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBackground.png
new file mode 100644
index 0000000..b466a49
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBackground.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBottomBackground.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBottomBackground.png
new file mode 100644
index 0000000..fb5c9e4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarBottomBackground.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarButtons.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarButtons.png
new file mode 100644
index 0000000..e8090cb
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarButtons.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButton.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButton.png
new file mode 100644
index 0000000..9b3abdd
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButton.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButtonSelected.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButtonSelected.png
new file mode 100644
index 0000000..8189c43
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarMenuButtonSelected.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerHorizontal.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerHorizontal.png
new file mode 100644
index 0000000..56deeab
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerHorizontal.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerVertical.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerVertical.png
new file mode 100644
index 0000000..7fc1452
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/statusbarResizerVertical.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/successGreenDot.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/successGreenDot.png
new file mode 100644
index 0000000..8b9319c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/successGreenDot.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveHoriz.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveHoriz.png
new file mode 100644
index 0000000..a6ee561
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveHoriz.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveVert.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveVert.png
new file mode 100644
index 0000000..a3eabe8
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbActiveVert.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoriz.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoriz.png
new file mode 100644
index 0000000..c16559a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoriz.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverHoriz.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverHoriz.png
new file mode 100644
index 0000000..0fe8d6a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverHoriz.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverVert.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverVert.png
new file mode 100644
index 0000000..30e315a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbHoverVert.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbVert.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbVert.png
new file mode 100644
index 0000000..61fbc06
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/thumbVert.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarBlue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarBlue.png
new file mode 100644
index 0000000..22641b5
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarBlue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGray.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGray.png
new file mode 100644
index 0000000..f66cf43
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGray.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGreen.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGreen.png
new file mode 100644
index 0000000..cc59082
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarGreen.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarOrange.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarOrange.png
new file mode 100644
index 0000000..e5ae6f5
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarOrange.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarPurple.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarPurple.png
new file mode 100644
index 0000000..f891252
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarPurple.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarRed.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarRed.png
new file mode 100644
index 0000000..b850037
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarRed.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarYellow.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarYellow.png
new file mode 100644
index 0000000..2b3e9a7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineBarYellow.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineCheckmarks.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineCheckmarks.png
new file mode 100644
index 0000000..9afa9bb
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineCheckmarks.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineDots.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineDots.png
new file mode 100644
index 0000000..e9ba4d3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineDots.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillBlue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillBlue.png
new file mode 100644
index 0000000..c7c273b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillBlue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGray.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGray.png
new file mode 100644
index 0000000..9ff37ef
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGray.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGreen.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGreen.png
new file mode 100644
index 0000000..cc5a8f3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillGreen.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillOrange.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillOrange.png
new file mode 100644
index 0000000..08a81e4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillOrange.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillPurple.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillPurple.png
new file mode 100644
index 0000000..565a05c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillPurple.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillRed.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillRed.png
new file mode 100644
index 0000000..c3a1b9b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillRed.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillYellow.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillYellow.png
new file mode 100644
index 0000000..780045b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineHollowPillYellow.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineIcon.png
new file mode 100644
index 0000000..09bcf30
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelineIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillBlue.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillBlue.png
new file mode 100644
index 0000000..c897faa
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillBlue.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGray.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGray.png
new file mode 100644
index 0000000..2128896
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGray.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGreen.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGreen.png
new file mode 100644
index 0000000..9b66125
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillGreen.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillOrange.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillOrange.png
new file mode 100644
index 0000000..dd944fb
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillOrange.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillPurple.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillPurple.png
new file mode 100644
index 0000000..21b96f7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillPurple.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillRed.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillRed.png
new file mode 100644
index 0000000..f5e213b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillRed.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillYellow.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillYellow.png
new file mode 100644
index 0000000..ae2a5a2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/timelinePillYellow.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/toolbarItemSelected.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/toolbarItemSelected.png
new file mode 100644
index 0000000..bd681f1
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/toolbarItemSelected.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackHoriz.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackHoriz.png
new file mode 100644
index 0000000..517d306
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackHoriz.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackVert.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackVert.png
new file mode 100644
index 0000000..d49620d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/trackVert.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleBlack.png
new file mode 100644
index 0000000..0821112
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleWhite.png
new file mode 100644
index 0000000..1667b51
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeDownTriangleWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleBlack.png
new file mode 100644
index 0000000..90de820
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleWhite.png
new file mode 100644
index 0000000..2b6a82f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeRightTriangleWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleBlack.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleBlack.png
new file mode 100644
index 0000000..ef69dbc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleBlack.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleWhite.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleWhite.png
new file mode 100644
index 0000000..43ce4be
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/treeUpTriangleWhite.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/undockButtonGlyph.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/undockButtonGlyph.png
new file mode 100644
index 0000000..eed2b65
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/undockButtonGlyph.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputIcon.png
new file mode 100644
index 0000000..325023f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputPreviousIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputPreviousIcon.png
new file mode 100644
index 0000000..068d572
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputPreviousIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputResultIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputResultIcon.png
new file mode 100644
index 0000000..794a5ca
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/userInputResultIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningIcon.png
new file mode 100644
index 0000000..d5e4c82
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningMediumIcon.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningMediumIcon.png
new file mode 100644
index 0000000..291e111
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningMediumIcon.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningOrangeDot.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningOrangeDot.png
new file mode 100644
index 0000000..8c8b635
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningOrangeDot.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningsErrors.png b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningsErrors.png
new file mode 100644
index 0000000..878b593
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Images/warningsErrors.png
Binary files differ
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/InjectedFakeWorker.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InjectedFakeWorker.js
new file mode 100644
index 0000000..7176844
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InjectedFakeWorker.js
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var InjectedFakeWorker = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
+{
+
+Worker = function(url)
+{
+    var impl = new FakeWorker(this, url);
+    if (impl === null)
+        return null;
+
+    this.isFake = true;
+    this.postMessage = bind(impl.postMessage, impl);
+    this.terminate = bind(impl.terminate, impl);
+
+    function onmessageGetter()
+    {
+        return impl.channel.port1.onmessage;
+    }
+    function onmessageSetter(callback)
+    {
+        impl.channel.port1.onmessage = callback;
+    }
+    this.__defineGetter__("onmessage", onmessageGetter);
+    this.__defineSetter__("onmessage", onmessageSetter);
+    this.addEventListener = bind(impl.channel.port1.addEventListener, impl.channel.port1);
+    this.removeEventListener = bind(impl.channel.port1.removeEventListener, impl.channel.port1);
+    this.dispatchEvent = bind(impl.channel.port1.dispatchEvent, impl.channel.port1);
+}
+
+function FakeWorker(worker, url)
+{
+    var scriptURL = this._expandURLAndCheckOrigin(document.baseURI, location.href, url);
+
+    this._worker = worker;
+    this._id = InjectedScriptHost.nextWorkerId();
+    this.channel = new MessageChannel();
+    this._listeners = [];
+    this._buildWorker(scriptURL);
+
+    InjectedScriptHost.didCreateWorker(this._id, scriptURL.url, false);
+}
+
+FakeWorker.prototype = {
+    postMessage: function(msg, opt_ports)
+    {
+        if (this._frame != null)
+            this.channel.port1.postMessage.apply(this.channel.port1, arguments);
+        else if (this._pendingMessages)
+            this._pendingMessages.push(arguments)
+        else
+            this._pendingMessages = [ arguments ];
+    },
+
+    terminate: function()
+    {
+        InjectedScriptHost.didDestroyWorker(this._id);
+
+        this.channel.port1.close();
+        this.channel.port2.close();
+        if (this._frame != null)
+            this._frame.frameElement.parentNode.removeChild(this._frame.frameElement);
+        this._frame = null;
+        this._worker = null; // Break reference loop.
+    },
+
+    _buildWorker: function(url)
+    {
+        var code = this._loadScript(url.url);
+        var iframeElement = document.createElement("iframe");
+        iframeElement.style.display = "none";
+
+        this._document = document;
+        iframeElement.onload = bind(this._onWorkerFrameLoaded, this, iframeElement, url, code);
+
+        if (document.body)
+            this._attachWorkerFrameToDocument(iframeElement, url, code);
+        else
+            window.addEventListener("load", bind(this._attachWorkerFrameToDocument, this, iframeElement), false);
+    },
+
+    _attachWorkerFrameToDocument: function(iframeElement)
+    {
+        document.body.appendChild(iframeElement);
+    },
+
+    _onWorkerFrameLoaded: function(iframeElement, url, code)
+    {
+        var frame = iframeElement.contentWindow;
+        this._frame = frame;
+        this._setupWorkerContext(frame, url);
+
+        var frameContents = '(function() { var location = __devtools.location; var window; ' + code + '})();\n' + '//@ sourceURL=' + url.url;
+
+        frame.eval(frameContents);
+        if (this._pendingMessages) {
+            for (var msg = 0; msg < this._pendingMessages.length; ++msg)
+                this.postMessage.apply(this, this._pendingMessages[msg]);
+            delete this._pendingMessages;
+        }
+    },
+
+    _setupWorkerContext: function(workerFrame, url)
+    {
+        workerFrame.__devtools = {
+            handleException: bind(this._handleException, this),
+            location: url.mockLocation()
+        };
+
+        var self = this;
+
+        function onmessageGetter()
+        {
+            return self.channel.port2.onmessage ? self.channel.port2.onmessage.originalCallback : null;
+        }
+
+        function onmessageSetter(callback)
+        {
+            var wrappedCallback = bind(self._callbackWrapper, self, callback);
+            wrappedCallback.originalCallback = callback;
+            self.channel.port2.onmessage = wrappedCallback;
+        }
+
+        workerFrame.__defineGetter__("onmessage", onmessageGetter);
+        workerFrame.__defineSetter__("onmessage", onmessageSetter);
+        workerFrame.addEventListener = bind(this._addEventListener, this);
+        workerFrame.removeEventListener = bind(this._removeEventListener, this);
+        workerFrame.dispatchEvent = bind(this.channel.port2.dispatchEvent, this.channel.port2);
+        workerFrame.postMessage = bind(this.channel.port2.postMessage, this.channel.port2);
+        workerFrame.importScripts = bind(this._importScripts, this, workerFrame);
+        workerFrame.close = bind(this.terminate, this);
+    },
+
+    _addEventListener: function(type, callback, useCapture)
+    {
+        var wrappedCallback = bind(this._callbackWrapper, this, callback);
+        wrappedCallback.originalCallback = callback;
+        wrappedCallback.type = type;
+        wrappedCallback.useCapture = Boolean(useCapture);
+
+        this.channel.port2.addEventListener(type, wrappedCallback, useCapture);
+        this._listeners.push(wrappedCallback);
+    },
+
+    _removeEventListener: function(type, callback, useCapture)
+    {
+        var listeners = this._listeners;
+        for (var i = 0; i < listeners.length; ++i) {
+            if (listeners[i].originalCallback === callback &&
+                listeners[i].type === type && 
+                listeners[i].useCapture === Boolean(useCapture)) {
+                this.channel.port2.removeEventListener(type, listeners[i], useCapture);
+                listeners[i] = listeners[listeners.length - 1];
+                listeners.pop();
+                break;
+            }
+        }
+    },
+
+    _callbackWrapper: function(callback, msg)
+    {
+        // Shortcut -- if no exception handlers installed, avoid try/catch so as not to obscure line number.
+        if (!this._frame.onerror && !this._worker.onerror) {
+            callback(msg);
+            return;
+        }
+
+        try {
+            callback(msg);
+        } catch (e) {
+            this._handleException(e, this._frame.onerror, this._worker.onerror);
+        }
+    },
+
+    _handleException: function(e)
+    {
+        // NB: it should be an ErrorEvent, but creating it from script is not
+        // currently supported, so emulate it on top of plain vanilla Event.
+        var errorEvent = this._document.createEvent("Event");
+        errorEvent.initEvent("Event", false, false);
+        errorEvent.message = "Uncaught exception";
+
+        for (var i = 1; i < arguments.length; ++i) {
+            if (arguments[i] && arguments[i](errorEvent))
+                return;
+        }
+
+        throw e;
+    },
+
+    _importScripts: function(targetFrame)
+    {
+        for (var i = 1; i < arguments.length; ++i) {
+            var workerOrigin = targetFrame.__devtools.location.href;
+            var url = this._expandURLAndCheckOrigin(workerOrigin, workerOrigin, arguments[i]);
+            targetFrame.eval(this._loadScript(url.url) + "\n//@ sourceURL= " + url.url);
+        }
+    },
+
+    _loadScript: function(url)
+    {
+        var xhr = new XMLHttpRequest();
+        xhr.open("GET", url, false);
+        xhr.send(null);
+
+        var text = xhr.responseText;
+        if (xhr.status != 0 && xhr.status/100 !== 2) { // We're getting status === 0 when using file://.
+            console.error("Failed to load worker: " + url + "[" + xhr.status + "]");
+            text = ""; // We've got error message, not worker code.
+        }
+        return text;
+    },
+
+    _expandURLAndCheckOrigin: function(baseURL, origin, url)
+    {
+        var scriptURL = new URL(baseURL).completeWith(url);
+
+        if (!scriptURL.sameOrigin(origin))
+            throw new DOMCoreException("SECURITY_ERR",18);
+        return scriptURL;
+    }
+};
+
+function URL(url)
+{
+    this.url = url;
+    this.split();
+}
+
+URL.prototype = {
+    urlRegEx: (/^(http[s]?|file):\/\/([^\/:]*)(:[\d]+)?(?:(\/[^#?]*)(\?[^#]*)?(?:#(.*))?)?$/i),
+
+    split: function()
+    {
+        function emptyIfNull(str)
+        {
+            return str == null ? "" : str;
+        }
+        var parts = this.urlRegEx.exec(this.url);
+
+        this.schema = parts[1];
+        this.host = parts[2];
+        this.port = emptyIfNull(parts[3]);
+        this.path = emptyIfNull(parts[4]);
+        this.query = emptyIfNull(parts[5]);
+        this.fragment = emptyIfNull(parts[6]);
+    },
+
+    mockLocation: function()
+    {
+        var host = this.host.replace(/^[^@]*@/, "");
+
+        return {
+            href:     this.url,
+            protocol: this.schema + ":",
+            host:     host,
+            hostname: host,
+            port:     this.port,
+            pathname: this.path,
+            search:   this.query,
+            hash:     this.fragment
+        };
+    },
+
+    completeWith: function(url)
+    {
+        if (url === "" || /^[^/]*:/.exec(url)) // If given absolute url, return as is now.
+            return new URL(url);
+
+        var relParts = /^([^#?]*)(.*)$/.exec(url); // => [ url, path, query-andor-fragment ]
+
+        var path = (relParts[1].slice(0, 1) === "/" ? "" : this.path.replace(/[^/]*$/, "")) + relParts[1];
+        path = path.replace(/(\/\.)+(\/|$)/g, "/").replace(/[^/]*\/\.\.(\/|$)/g, "");
+
+        return new URL(this.schema + "://" + this.host + this.port + path + relParts[2]);
+    },
+
+    sameOrigin: function(url)
+    {
+        function normalizePort(schema, port)
+        {
+            var portNo = port.slice(1);
+            return (schema === "https" && portNo == 443 || schema === "http" && portNo == 80) ? "" : port;
+        }
+
+        var other = new URL(url);
+
+        return this.schema === other.schema &&
+            this.host === other.host &&
+            normalizePort(this.schema, this.port) === normalizePort(other.schema, other.port);
+    }
+};
+
+function DOMCoreException(name, code)
+{
+    function formatError()
+    {
+        return "Error: " + this.message;
+    }
+
+    this.name = name;
+    this.message = name + ": DOM Exception " + code;
+    this.code = code;
+    this.toString = bind(formatError, this);
+}
+
+function bind(func, thisObject)
+{
+    var args = Array.prototype.slice.call(arguments, 2);
+    return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); };
+}
+
+function noop()
+{
+}
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorBackendStub.qrc b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorBackendStub.qrc
new file mode 100644
index 0000000..30f6d75
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorBackendStub.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/webkit/inspector">
+    <file>InspectorBackendStub.js</file>
+</qresource>
+</RCC>
+
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorFrontendHostStub.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorFrontendHostStub.js
new file mode 100644
index 0000000..07f392d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/InspectorFrontendHostStub.js
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!window.InspectorFrontendHost) {
+
+WebInspector.InspectorFrontendHostStub = function()
+{
+    this._attachedWindowHeight = 0;
+}
+
+WebInspector._platformFlavor = WebInspector.PlatformFlavor.MacLeopard;
+
+WebInspector.InspectorFrontendHostStub.prototype = {
+    platform: function()
+    {
+        var match = navigator.userAgent.match(/Windows NT/);
+        if (match)
+            return "windows";
+        match = navigator.userAgent.match(/Mac OS X/);
+        if (match)
+            return "mac";
+        return "linux";
+    },
+
+    port: function()
+    {
+        return "unknown";
+    },
+
+    bringToFront: function()
+    {
+        this._windowVisible = true;
+    },
+
+    closeWindow: function()
+    {
+        this._windowVisible = false;
+    },
+
+    disconnectFromBackend: function()
+    {
+        this._windowVisible = false;
+    },
+
+    attach: function()
+    {
+    },
+
+    detach: function()
+    {
+    },
+
+    search: function(sourceRow, query)
+    {
+    },
+
+    setAttachedWindowHeight: function(height)
+    {
+    },
+
+    moveWindowBy: function(x, y)
+    {
+    },
+
+    setExtensionAPI: function(script)
+    {
+    },
+
+    loaded: function()
+    {
+    },
+
+    localizedStringsURL: function()
+    {
+        return undefined;
+    },
+
+    hiddenPanels: function()
+    {
+        return "";
+    },
+
+    inspectedURLChanged: function(url)
+    {
+    },
+
+    copyText: function()
+    {
+    },
+
+    canAttachWindow: function()
+    {
+        return false;
+    },
+
+    sendMessageToBackend: function(message)
+    {
+    }
+}
+
+InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub();
+
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/KeyboardShortcut.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/KeyboardShortcut.js
new file mode 100644
index 0000000..2bcf3d1
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/KeyboardShortcut.js
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.KeyboardShortcut = function()
+{
+};
+
+/**
+ * Constants for encoding modifier key set as a bit mask.
+ * @see #_makeKeyFromCodeAndModifiers
+ */
+WebInspector.KeyboardShortcut.Modifiers = {
+    None: 0,   // Constant for empty modifiers set.
+    Shift: 1,
+    Ctrl: 2,
+    Alt: 4,
+    Meta: 8,   // Command key on Mac, Win key on other platforms.
+    get CtrlOrMeta()
+    {
+        // "default" command/ctrl key for platform, Command on Mac, Ctrl on other platforms
+        return WebInspector.isMac() ? this.Meta : this.Ctrl;
+    }
+};
+
+WebInspector.KeyboardShortcut.Keys = {
+    Backspace: { code: 8, name: "\u21a4" },
+    Tab: { code: 9, name: { mac: "\u21e5", other: "<Tab>" } },
+    Enter: { code: 13, name: { mac: "\u21a9", other: "<Enter>" } },
+    Esc: { code: 27, name: { mac: "\u238b", other: "<Esc>" } },
+    Space: { code: 32, name: "<Space>" },
+    PageUp: { code: 33,  name: { mac: "\u21de", other: "<PageUp>" } },      // also NUM_NORTH_EAST
+    PageDown: { code: 34, name: { mac: "\u21df", other: "<PageDown>" } },   // also NUM_SOUTH_EAST
+    End: { code: 35, name: { mac: "\u2197", other: "<End>" } },             // also NUM_SOUTH_WEST
+    Home: { code: 36, name: { mac: "\u2196", other: "<Home>" } },           // also NUM_NORTH_WEST
+    Left: { code: 37, name: "\u2190" },           // also NUM_WEST
+    Up: { code: 38, name: "\u2191" },             // also NUM_NORTH
+    Right: { code: 39, name: "\u2192" },          // also NUM_EAST
+    Down: { code: 40, name: "\u2193" },           // also NUM_SOUTH
+    Delete: { code: 46, name: "<Del>" },
+    Zero: { code: 48, name: "0" },
+    F1: { code: 112, name: "F1" },
+    F2: { code: 113, name: "F2" },
+    F3: { code: 114, name: "F3" },
+    F4: { code: 115, name: "F4" },
+    F5: { code: 116, name: "F5" },
+    F6: { code: 117, name: "F6" },
+    F7: { code: 118, name: "F7" },
+    F8: { code: 119, name: "F8" },
+    F9: { code: 120, name: "F9" },
+    F10: { code: 121, name: "F10" },
+    F11: { code: 122, name: "F11" },
+    F12: { code: 123, name: "F12" },
+    Semicolon: { code: 186, name: ";" },
+    Plus: { code: 187, name: "+" },
+    Comma: { code: 188, name: "," },
+    Minus: { code: 189, name: "-" },
+    Period: { code: 190, name: "." },
+    Slash: { code: 191, name: "/" },
+    Apostrophe: { code: 192, name: "`" },
+    SingleQuote: { code: 222, name: "\'" }
+};
+
+/**
+ * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits.
+ * It is useful for matching pressed keys.
+ * keyCode is the Code of the key, or a character "a-z" which is converted to a keyCode value.
+ * optModifiers is an Optional list of modifiers passed as additional paramerters.
+ */
+WebInspector.KeyboardShortcut.makeKey = function(keyCode, optModifiers)
+{
+    if (typeof keyCode === "string")
+        keyCode = keyCode.charCodeAt(0) - 32;
+    var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
+    for (var i = 1; i < arguments.length; i++)
+        modifiers |= arguments[i];
+    return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
+};
+
+WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent)
+{
+    var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
+    if (keyboardEvent.shiftKey)
+        modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift;
+    if (keyboardEvent.ctrlKey)
+        modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl;
+    if (keyboardEvent.altKey)
+        modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt;
+    if (keyboardEvent.metaKey)
+        modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta;
+    return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers);
+};
+
+WebInspector.KeyboardShortcut.makeDescriptor = function(key, optModifiers)
+{
+    var modifiers = 0;
+    for (var i = 1; i < arguments.length; i++)
+        modifiers |= arguments[i];
+
+    return {
+        key: WebInspector.KeyboardShortcut.makeKey(typeof key === "string" ? key : key.code, modifiers),
+        name: WebInspector.KeyboardShortcut.shortcutToString(key, modifiers)
+    };
+}
+
+WebInspector.KeyboardShortcut.shortcutToString = function(key, modifiers)
+{
+    return WebInspector.KeyboardShortcut._modifiersToString(modifiers) + WebInspector.KeyboardShortcut._keyName(key);
+}
+
+WebInspector.KeyboardShortcut._keyName = function(key)
+{
+    if (typeof key === "string")
+        return key.toUpperCase();
+    if (typeof key.name === "string")
+        return key.name;
+    return key.name[WebInspector.platform] || key.name.other;
+}
+
+WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers)
+{
+    return (keyCode & 255) | (modifiers << 8);
+};
+
+WebInspector.KeyboardShortcut._modifiersToString = function(modifiers)
+{
+    const cmdKey = "\u2318";
+    const optKey = "\u2325";
+    const shiftKey = "\u21e7";
+    const ctrlKey = "\u2303";
+
+    var isMac = WebInspector.isMac();
+    var res = "";
+    if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Ctrl)
+        res += isMac ? ctrlKey : "<Ctrl> + ";
+    if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Alt)
+        res += isMac ? optKey : "<Alt> + ";
+    if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Shift)
+        res += isMac ? shiftKey : "<Shift> + ";
+    if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Meta)
+        res += isMac ? cmdKey : "<Win> + ";
+
+    return res;
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/MetricsSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/MetricsSidebarPane.js
new file mode 100644
index 0000000..3c0f315
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.MetricsSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));
+    this._inlineStyleId = null;
+}
+
+WebInspector.MetricsSidebarPane.prototype = {
+    update: function(node)
+    {
+        if (node)
+            this.node = node;
+        else
+            node = this.node;
+
+        if (!node || !node.ownerDocument.defaultView || node.nodeType !== Node.ELEMENT_NODE) {
+            this.bodyElement.removeChildren();
+            return;
+        }
+
+        var self = this;
+        var callback = function(style) {
+            if (!style)
+                return;
+            self._update(style);
+        };
+        WebInspector.cssModel.getComputedStyleAsync(node.id, callback);
+
+        var inlineStyleCallback = function(style) {
+            if (!style)
+                return;
+            self.inlineStyle = style;
+        };
+        WebInspector.cssModel.getInlineStyleAsync(node.id, inlineStyleCallback);
+    },
+
+    _update: function(style)
+    {
+        // Updating with computed style.
+        var metricsElement = document.createElement("div");
+        metricsElement.className = "metrics";
+
+        function createBoxPartElement(style, name, side, suffix)
+        {
+            var propertyName = (name !== "position" ? name + "-" : "") + side + suffix;
+            var value = style.getPropertyValue(propertyName);
+            if (value === "" || (name !== "position" && value === "0px"))
+                value = "\u2012";
+            else if (name === "position" && value === "auto")
+                value = "\u2012";
+            value = value.replace(/px$/, "");
+
+            var element = document.createElement("div");
+            element.className = side;
+            element.textContent = value;
+            element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName), false);
+            return element;
+        }
+
+        // Display types for which margin is ignored.
+        var noMarginDisplayType = {
+            "table-cell": true,
+            "table-column": true,
+            "table-column-group": true,
+            "table-footer-group": true,
+            "table-header-group": true,
+            "table-row": true,
+            "table-row-group": true
+        };
+
+        // Display types for which padding is ignored.
+        var noPaddingDisplayType = {
+            "table-column": true,
+            "table-column-group": true,
+            "table-footer-group": true,
+            "table-header-group": true,
+            "table-row": true,
+            "table-row-group": true
+        };
+
+        // Position types for which top, left, bottom and right are ignored.
+        var noPositionType = {
+            "static": true
+        };
+
+        var boxes = ["content", "padding", "border", "margin", "position"];
+        var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")];
+        var previousBox;
+        for (var i = 0; i < boxes.length; ++i) {
+            var name = boxes[i];
+
+            if (name === "margin" && noMarginDisplayType[style.getPropertyValue("display")])
+                continue;
+            if (name === "padding" && noPaddingDisplayType[style.getPropertyValue("display")])
+                continue;
+            if (name === "position" && noPositionType[style.getPropertyValue("position")])
+                continue;
+
+            var boxElement = document.createElement("div");
+            boxElement.className = name;
+
+            if (name === "content") {
+                var width = style.getPropertyValue("width").replace(/px$/, "");
+                var widthElement = document.createElement("span");
+                widthElement.textContent = width;
+                widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false);
+
+                var height = style.getPropertyValue("height").replace(/px$/, "");
+                var heightElement = document.createElement("span");
+                heightElement.textContent = height;
+                heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false);
+
+                boxElement.appendChild(widthElement);
+                boxElement.appendChild(document.createTextNode(" \u00D7 "));
+                boxElement.appendChild(heightElement);
+            } else {
+                var suffix = (name === "border" ? "-width" : "");
+
+                var labelElement = document.createElement("div");
+                labelElement.className = "label";
+                labelElement.textContent = boxLabels[i];
+                boxElement.appendChild(labelElement);
+
+                boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix));
+                boxElement.appendChild(document.createElement("br"));
+                boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix));
+
+                if (previousBox)
+                    boxElement.appendChild(previousBox);
+
+                boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix));
+                boxElement.appendChild(document.createElement("br"));
+                boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix));
+            }
+
+            previousBox = boxElement;
+        }
+
+        metricsElement.appendChild(previousBox);
+        this.bodyElement.removeChildren();
+        this.bodyElement.appendChild(metricsElement);
+    },
+
+    startEditing: function(targetElement, box, styleProperty)
+    {
+        if (WebInspector.isBeingEdited(targetElement))
+            return;
+
+        var context = { box: box, styleProperty: styleProperty };
+
+        WebInspector.startEditing(targetElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
+    },
+
+    editingCancelled: function(element, context)
+    {
+        this.update();
+    },
+
+    editingCommitted: function(element, userInput, previousContent, context)
+    {
+        if (!this.inlineStyle) {
+            // Element has no renderer.
+            return this.editingCancelled(element, context); // nothing changed, so cancel
+        }
+
+        if (userInput === previousContent)
+            return this.editingCancelled(element, context); // nothing changed, so cancel
+
+        if (context.box !== "position" && (!userInput || userInput === "\u2012"))
+            userInput = "0px";
+        else if (context.box === "position" && (!userInput || userInput === "\u2012"))
+            userInput = "auto";
+
+        // Append a "px" unit if the user input was just a number.
+        if (/^\d+$/.test(userInput))
+            userInput += "px";
+
+        var self = this;
+        var callback = function(style) {
+            if (!style)
+                return;
+            self.inlineStyle = style;
+            self.dispatchEventToListeners("metrics edited");
+            self.update();
+        };
+
+        function setEnabledValueCallback(context, style)
+        {
+            var property = style.getLiveProperty(context.styleProperty);
+            if (!property)
+                style.appendProperty(context.styleProperty, userInput, callback);
+             else
+                property.setValue(userInput, callback);
+        }
+
+        var allProperties = this.inlineStyle.allProperties;
+        for (var i = 0; i < allProperties.length; ++i) {
+            var property = allProperties[i];
+            if (property.name !== context.styleProperty || property.inactive)
+                continue;
+            if (property.disabled)
+                property.setDisabled(false, setEnabledValueCallback.bind(null, context));
+            else
+                property.setValue(userInput, callback);
+            return;
+        }
+
+        this.inlineStyle.appendProperty(context.styleProperty, userInput, callback);
+    }
+}
+
+WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkItemView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkItemView.js
new file mode 100644
index 0000000..418f559
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkItemView.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.NetworkItemView = function(resource)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("network-item-view");
+
+    this._headersView = new WebInspector.ResourceHeadersView(resource);
+    // Do not store reference to content view - it can be recreated.
+    var contentView = WebInspector.ResourceView.resourceViewForResource(resource);
+
+    this._tabbedPane = new WebInspector.TabbedPane(this.element);
+    this._tabbedPane.appendTab("headers", WebInspector.UIString("Headers"), this._headersView);
+    if (contentView.hasContent()) {
+        // Reusing this view, so hide it at first.
+        contentView.visible = false;
+        this._tabbedPane.appendTab("content", WebInspector.UIString("Content"), contentView);
+    }
+    if (Preferences.showCookiesTab) {
+        this._cookiesView = new WebInspector.ResourceCookiesView(resource);
+        this._tabbedPane.appendTab("cookies", WebInspector.UIString("Cookies"), this._cookiesView);
+    }
+    if (Preferences.showTimingTab) {
+        var timingView = new WebInspector.ResourceTimingView(resource);
+        this._tabbedPane.appendTab("timing", WebInspector.UIString("Timing"), timingView);
+    }
+
+    this._tabbedPane.addEventListener("tab-selected", this._tabSelected, this);
+}
+
+WebInspector.NetworkItemView.prototype = {
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this._selectTab();
+    },
+
+    _selectTab: function(tabId)
+    {
+        if (!tabId)
+            tabId = WebInspector.settings.resourceViewTab;
+
+        if (!this._tabbedPane.selectTab(tabId)) {
+            this._isInFallbackSelection = true;
+            this._tabbedPane.selectTab("headers");
+            delete this._isInFallbackSelection;
+        }
+    },
+
+    _tabSelected: function(event)
+    {
+        WebInspector.settings.resourceViewTab = event.data.tabId;
+    },
+
+    resize: function()
+    {
+        if (this._cookiesView && this._cookiesView.visible)
+            this._cookiesView.resize();
+    }
+}
+
+WebInspector.NetworkItemView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkManager.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkManager.js
new file mode 100644
index 0000000..da043fe
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkManager.js
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.NetworkManager = function(resourceTreeModel)
+{
+    WebInspector.Object.call(this);
+    this._resourceTreeModel = resourceTreeModel;
+    this._dispatcher = new WebInspector.NetworkDispatcher(resourceTreeModel, this);
+    InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+}
+
+WebInspector.NetworkManager.EventTypes = {
+    ResourceStarted: "ResourceStarted",
+    ResourceUpdated: "ResourceUpdated",
+    ResourceFinished: "ResourceFinished",
+    MainResourceCommitLoad: "MainResourceCommitLoad"
+}
+
+WebInspector.NetworkManager.prototype = {
+    reset: function()
+    {
+        WebInspector.panels.network.clear();
+        this._resourceTreeModel.reset();
+        InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+    },
+
+    requestContent: function(resource, base64Encode, callback)
+    {
+        function callbackWrapper(success, content)
+        {
+            callback(success ? content : null);
+        }
+        InspectorBackend.resourceContent(resource.loader.frameId, resource.url, base64Encode, callbackWrapper);
+    },
+
+    _processCachedResources: function(mainFramePayload)
+    {
+        var mainResource = this._dispatcher._addFramesRecursively(mainFramePayload);
+        WebInspector.mainResource = mainResource;
+        mainResource.isMainResource = true;
+    },
+
+    inflightResourceForURL: function(url)
+    {
+        return this._dispatcher._inflightResourcesByURL[url];
+    }
+}
+
+WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.NetworkDispatcher = function(resourceTreeModel, manager)
+{
+    this._manager = manager;
+    this._inflightResourcesById = {};
+    this._inflightResourcesByURL = {};
+    this._resourceTreeModel = resourceTreeModel;
+    this._lastIdentifierForCachedResource = 0;
+    InspectorBackend.registerDomainDispatcher("Network", this);
+}
+
+WebInspector.NetworkDispatcher.prototype = {
+    _updateResourceWithRequest: function(resource, request)
+    {
+        resource.requestMethod = request.httpMethod;
+        resource.requestHeaders = request.httpHeaderFields;
+        resource.requestFormData = request.requestFormData;
+    },
+
+    _updateResourceWithResponse: function(resource, response)
+    {
+        if (resource.isNull)
+            return;
+
+        resource.mimeType = response.mimeType;
+        resource.expectedContentLength = response.expectedContentLength;
+        resource.textEncodingName = response.textEncodingName;
+        resource.suggestedFilename = response.suggestedFilename;
+        resource.statusCode = response.httpStatusCode;
+        resource.statusText = response.httpStatusText;
+
+        resource.responseHeaders = response.httpHeaderFields;
+        resource.connectionReused = response.connectionReused;
+        resource.connectionID = response.connectionID;
+
+        if (response.wasCached)
+            resource.cached = true;
+        else
+            resource.timing = response.timing;
+
+        if (response.loadInfo) {
+            if (response.loadInfo.httpStatusCode)
+                resource.statusCode = response.loadInfo.httpStatusCode;
+            if (response.loadInfo.httpStatusText)
+                resource.statusText = response.loadInfo.httpStatusText;
+            resource.requestHeaders = response.loadInfo.requestHeaders;
+            resource.responseHeaders = response.loadInfo.responseHeaders;
+        }
+    },
+
+    _updateResourceWithCachedResource: function(resource, cachedResource)
+    {
+        resource.type = WebInspector.Resource.Type[cachedResource.type];
+        resource.resourceSize = cachedResource.encodedSize;
+        this._updateResourceWithResponse(resource, cachedResource.response);
+    },
+
+    identifierForInitialRequest: function(identifier, url, loader, callStack)
+    {
+        this._startResource(this._createResource(identifier, url, loader, callStack));
+    },
+
+    willSendRequest: function(identifier, time, request, redirectResponse)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        // Redirect may have empty URL and we'd like to not crash with invalid HashMap entry.
+        // See http/tests/misc/will-send-request-returns-null-on-redirect.html
+        var isRedirect = !redirectResponse.isNull && request.url.length;
+        if (isRedirect) {
+            this.didReceiveResponse(identifier, time, "Other", redirectResponse);
+            resource = this._appendRedirect(resource.identifier, time, request.url);
+        }
+
+        this._updateResourceWithRequest(resource, request);
+        resource.startTime = time;
+
+        if (isRedirect)
+            this._startResource(resource);
+        else
+            this._updateResource(resource);
+    },
+
+    markResourceAsCached: function(identifier)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.cached = true;
+        this._updateResource(resource);
+    },
+
+    didReceiveResponse: function(identifier, time, resourceType, response)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.responseReceivedTime = time;
+        resource.type = WebInspector.Resource.Type[resourceType];
+
+        this._updateResourceWithResponse(resource, response);
+
+        this._updateResource(resource);
+        this._resourceTreeModel.addResourceToFrame(resource.loader.frameId, resource);
+    },
+
+    didReceiveContentLength: function(identifier, time, lengthReceived)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.resourceSize += lengthReceived;
+        resource.endTime = time;
+
+        this._updateResource(resource);
+    },
+
+    didFinishLoading: function(identifier, finishTime)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        this._finishResource(resource, finishTime);
+    },
+
+    didFailLoading: function(identifier, time, localizedDescription)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.failed = true;
+        resource.localizedFailDescription = localizedDescription;
+        this._finishResource(resource, time);
+    },
+
+    didLoadResourceFromMemoryCache: function(time, cachedResource)
+    {
+        var resource = this._createResource("cached:" + ++this._lastIdentifierForCachedResource, cachedResource.url, cachedResource.loader);
+        this._updateResourceWithCachedResource(resource, cachedResource);
+        resource.cached = true;
+        resource.requestMethod = "GET";
+        this._startResource(resource);
+        resource.startTime = resource.responseReceivedTime = time;
+        this._finishResource(resource, time);
+        this._resourceTreeModel.addResourceToFrame(resource.loader.frameId, resource);
+    },
+
+    frameDetachedFromParent: function(frameId)
+    {
+        this._resourceTreeModel.frameDetachedFromParent(frameId);
+    },
+
+    setInitialContent: function(identifier, sourceString, type)
+    {
+        var resource = WebInspector.networkResourceById(identifier);
+        if (!resource)
+            return;
+
+        resource.type = WebInspector.Resource.Type[type];
+        resource.setInitialContent(sourceString);
+        this._updateResource(resource);
+    },
+
+    didCommitLoadForFrame: function(frame, loader)
+    {
+        this._resourceTreeModel.didCommitLoadForFrame(frame, loader);
+        if (!frame.parentId) {
+            var mainResource = this._resourceTreeModel.resourceForURL(frame.url);
+            if (mainResource) {
+                WebInspector.mainResource = mainResource;
+                mainResource.isMainResource = true;
+                this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.MainResourceCommitLoad, mainResource);
+            }
+        }
+    },
+
+    didCreateWebSocket: function(identifier, requestURL)
+    {
+        var resource = this._createResource(identifier, requestURL);
+        resource.type = WebInspector.Resource.Type.WebSocket;
+        this._startResource(resource);
+    },
+
+    willSendWebSocketHandshakeRequest: function(identifier, time, request)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.requestMethod = "GET";
+        resource.requestHeaders = request.webSocketHeaderFields;
+        resource.webSocketRequestKey3 = request.webSocketRequestKey3;
+        resource.startTime = time;
+
+        this._updateResource(resource);
+    },
+
+    didReceiveWebSocketHandshakeResponse: function(identifier, time, response)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+
+        resource.statusCode = response.statusCode;
+        resource.statusText = response.statusText;
+        resource.responseHeaders = response.webSocketHeaderFields;
+        resource.webSocketChallengeResponse = response.webSocketChallengeResponse;
+        resource.responseReceivedTime = time;
+
+        this._updateResource(resource);
+    },
+
+    didCloseWebSocket: function(identifier, time)
+    {
+        var resource = this._inflightResourcesById[identifier];
+        if (!resource)
+            return;
+        this._finishResource(resource, time);
+    },
+
+    _appendRedirect: function(identifier, time, redirectURL)
+    {
+        var originalResource = this._inflightResourcesById[identifier];
+        var previousRedirects = originalResource.redirects || [];
+        originalResource.identifier = "redirected:" + identifier + "." + previousRedirects.length;
+        delete originalResource.redirects;
+        this._finishResource(originalResource, time);
+        var newResource = this._createResource(identifier, redirectURL, originalResource.loader, originalResource.stackTrace);
+        newResource.redirects = previousRedirects.concat(originalResource);
+        return newResource;
+    },
+
+    _startResource: function(resource)
+    {
+        this._inflightResourcesById[resource.identifier] = resource;
+        this._inflightResourcesByURL[resource.url] = resource;
+        this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceStarted, resource);
+    },
+
+    _updateResource: function(resource)
+    {
+        this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdated, resource);
+    },
+
+    _finishResource: function(resource, finishTime)
+    {
+        resource.endTime = finishTime;
+        resource.finished = true;
+        this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceFinished, resource);
+        delete this._inflightResourcesById[resource.identifier];
+        delete this._inflightResourcesByURL[resource.url];
+    },
+
+    _addFramesRecursively: function(framePayload)
+    {
+        var frameResource = this._createResource(null, framePayload.resource.url, framePayload.resource.loader);
+        this._updateResourceWithRequest(frameResource, framePayload.resource.request);
+        this._updateResourceWithResponse(frameResource, framePayload.resource.response);
+        frameResource.type = WebInspector.Resource.Type["Document"];
+        frameResource.finished = true;
+
+        this._resourceTreeModel.addOrUpdateFrame(framePayload);
+        this._resourceTreeModel.addResourceToFrame(framePayload.id, frameResource);
+
+        for (var i = 0; framePayload.children && i < framePayload.children.length; ++i)
+            this._addFramesRecursively(framePayload.children[i]);
+
+        if (!framePayload.subresources)
+            return;
+
+        for (var i = 0; i < framePayload.subresources.length; ++i) {
+            var cachedResource = framePayload.subresources[i];
+            var resource = this._createResource(null, cachedResource.url, cachedResource.loader);
+            this._updateResourceWithCachedResource(resource, cachedResource);
+            resource.finished = true;
+            this._resourceTreeModel.addResourceToFrame(framePayload.id, resource);
+        }
+        return frameResource;
+    },
+
+    _dispatchEventToListeners: function(eventType, resource)
+    {
+        this._manager.dispatchEventToListeners(eventType, resource);
+    },
+
+    _createResource: function(identifier, url, loader, stackTrace)
+    {
+        var resource = new WebInspector.Resource(identifier, url);
+        resource.loader = loader;
+        if (loader)
+            resource.documentURL = loader.url;
+        resource.stackTrace = stackTrace;
+        return resource;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js
new file mode 100644
index 0000000..085f468
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/NetworkPanel.js
@@ -0,0 +1,1742 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.NetworkPanel = function()
+{
+    WebInspector.Panel.call(this, "network");
+
+    this.createSidebar();
+    this.sidebarElement.className = "network-sidebar";
+
+    this._resources = [];
+    this._resourcesById = {};
+    this._resourcesByURL = {};
+    this._staleResources = [];
+    this._resourceGridNodes = {};
+    this._mainResourceLoadTime = -1;
+    this._mainResourceDOMContentTime = -1;
+    this._hiddenCategories = {};
+
+    this._categories = WebInspector.resourceCategories;
+
+    this.containerElement = document.createElement("div");
+    this.containerElement.id = "network-container";
+    this.sidebarElement.appendChild(this.containerElement);
+
+    this._viewsContainerElement = document.createElement("div");
+    this._viewsContainerElement.id = "network-views";
+    this._viewsContainerElement.className = "hidden";
+    this.element.appendChild(this._viewsContainerElement);
+
+    this._closeButtonElement = document.createElement("button");
+    this._closeButtonElement.id = "network-close-button";
+    this._closeButtonElement.addEventListener("click", this._toggleGridMode.bind(this), false);
+    this._viewsContainerElement.appendChild(this._closeButtonElement);
+
+    this._createSortingFunctions();
+    this._createTable();
+    this._createTimelineGrid();
+    this._createStatusbarButtons();
+    this._createFilterStatusBarItems();
+    this._createSummaryBar();
+
+    if (!WebInspector.settings.resourcesLargeRows)
+        this._setLargerResources(WebInspector.settings.resourcesLargeRows);
+
+    this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);
+    // Enable faster hint.
+    this._popoverHelper.setTimeout(100);
+
+    this.calculator = new WebInspector.NetworkTransferTimeCalculator();
+    this._filter(this._filterAllElement, false);
+
+    this._toggleGridMode();
+
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this);
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.MainResourceCommitLoad, this._onMainResourceCommitLoad, this);
+}
+
+WebInspector.NetworkPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Network");
+    },
+
+    get statusBarItems()
+    {
+        return [this._largerResourcesButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
+    },
+
+    isCategoryVisible: function(categoryName)
+    {
+        return true;
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [this.containerElement, this._dataGrid.scrollContainer];
+    },
+
+    resize: function()
+    {
+        WebInspector.Panel.prototype.resize.call(this);
+        this._dataGrid.updateWidths();
+        this._positionSummaryBar();
+    },
+
+    updateSidebarWidth: function(width)
+    {
+        if (!this._viewingResourceMode)
+            return;
+        WebInspector.Panel.prototype.updateSidebarWidth.call(this, width);
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this._viewsContainerElement.style.left = width + "px";
+    },
+
+    handleShortcut: function(event)
+    {
+        if (this._viewingResourceMode && event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+            this._toggleGridMode();
+            event.handled = true;
+        }
+    },
+
+    _positionSummaryBar: function()
+    {
+        // Position the total bar.
+
+        var fillerRow = this._dataGrid.dataTableBody.lastChild;
+        if (this._summaryBarElement.parentElement !== this.element && fillerRow.offsetHeight > 0) {
+            // Glue status to bottom.
+            if (this._summaryBarRowNode) {
+                this._dataGrid.removeChild(this._summaryBarRowNode);
+                delete this._summaryBarRowNode;
+            }
+            this._summaryBarElement.addStyleClass("network-summary-bar-bottom");
+            this.element.appendChild(this._summaryBarElement);
+            this._dataGrid.element.style.bottom = "20px";
+            return;
+        }
+
+        if (!this._summaryBarRowNode && !fillerRow.offsetHeight) {
+            // Glue status to table.
+            this._summaryBarRowNode = new WebInspector.NetworkTotalGridNode(this._summaryBarElement);
+            this._summaryBarElement.removeStyleClass("network-summary-bar-bottom");
+            this._dataGrid.appendChild(this._summaryBarRowNode);
+            this._dataGrid.element.style.bottom = 0;
+            this._sortItems();
+        }
+        this._updateOffscreenRows();
+    },
+
+    _resetSummaryBar: function()
+    {
+        delete this._summaryBarRowNode;
+        this._summaryBarElement.parentElement.removeChild(this._summaryBarElement);
+        this._updateSummaryBar();
+    },
+
+    _createTimelineGrid: function()
+    {
+        this._timelineGrid = new WebInspector.TimelineGrid();
+        this._timelineGrid.element.addStyleClass("network-timeline-grid");
+        this._dataGrid.element.appendChild(this._timelineGrid.element);
+    },
+
+    _createTable: function()
+    {
+        var columns = {name: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}};
+        columns.name.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path"));
+        columns.name.sortable = true;
+        columns.name.width = "20%";
+        columns.name.disclosure = true;
+
+        columns.method.title = WebInspector.UIString("Method");
+        columns.method.sortable = true;
+        columns.method.width = "7%";
+
+        columns.status.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text"));
+        columns.status.sortable = true;
+        columns.status.width = "8%";
+
+        columns.type.title = WebInspector.UIString("Type");
+        columns.type.sortable = true;
+        columns.type.width = "10%";
+
+        columns.size.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Transfer"));
+        columns.size.sortable = true;
+        columns.size.width = "10%";
+        columns.size.aligned = "right";
+
+        columns.time.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency"));
+        columns.time.sortable = true;
+        columns.time.width = "10%";
+        columns.time.aligned = "right";
+
+        columns.timeline.title = "";
+        columns.timeline.sortable = false;
+        columns.timeline.width = "37%";
+        columns.timeline.sort = "ascending";
+
+        this._dataGrid = new WebInspector.DataGrid(columns);
+        this._dataGrid.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
+        this.containerElement.appendChild(this._dataGrid.element);
+        this._dataGrid.addEventListener("sorting changed", this._sortItems, this);
+        this._dataGrid.addEventListener("width changed", this._updateDividersIfNeeded, this);
+        this._dataGrid.scrollContainer.addEventListener("scroll", this._updateOffscreenRows.bind(this));
+
+        this._patchTimelineHeader();
+    },
+
+    _makeHeaderFragment: function(title, subtitle)
+    {
+        var fragment = document.createDocumentFragment();
+        fragment.appendChild(document.createTextNode(title));
+        var subtitleDiv = document.createElement("div");
+        subtitleDiv.className = "network-header-subtitle";
+        subtitleDiv.textContent = subtitle;
+        fragment.appendChild(subtitleDiv);
+        return fragment;
+    },
+
+    _patchTimelineHeader: function()
+    {
+        var timelineSorting = document.createElement("select");
+
+        var option = document.createElement("option");
+        option.value = "startTime";
+        option.label = WebInspector.UIString("Timeline");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "startTime";
+        option.label = WebInspector.UIString("Start Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "responseTime";
+        option.label = WebInspector.UIString("Response Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "endTime";
+        option.label = WebInspector.UIString("End Time");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "duration";
+        option.label = WebInspector.UIString("Duration");
+        timelineSorting.appendChild(option);
+
+        option = document.createElement("option");
+        option.value = "latency";
+        option.label = WebInspector.UIString("Latency");
+        timelineSorting.appendChild(option);
+
+        var header = this._dataGrid.headerTableHeader("timeline");
+        header.replaceChild(timelineSorting, header.firstChild);
+
+        timelineSorting.addEventListener("click", function(event) { event.stopPropagation() }, false);
+        timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false);
+        this._timelineSortSelector = timelineSorting;
+    },
+
+    _createSortingFunctions: function()
+    {
+        this._sortingFunctions = {};
+        this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator;
+        this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method", false);
+        this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode", false);
+        this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType", false);
+        this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator;
+        this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", false);
+        this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+        this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+        this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "endTime", false);
+        this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "responseReceivedTime", false);
+        this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", true);
+        this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "latency", true);
+
+        var timeCalculator = new WebInspector.NetworkTransferTimeCalculator();
+        var durationCalculator = new WebInspector.NetworkTransferDurationCalculator();
+
+        this._calculators = {};
+        this._calculators.timeline = timeCalculator;
+        this._calculators.startTime = timeCalculator;
+        this._calculators.endTime = timeCalculator;
+        this._calculators.responseTime = timeCalculator;
+        this._calculators.duration = durationCalculator;
+        this._calculators.latency = durationCalculator;
+    },
+
+    _sortItems: function()
+    {
+        var columnIdentifier = this._dataGrid.sortColumnIdentifier;
+        if (columnIdentifier === "timeline") {
+            this._sortByTimeline();
+            return;
+        }
+        var sortingFunction = this._sortingFunctions[columnIdentifier];
+        if (!sortingFunction)
+            return;
+
+        this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
+        this._timelineSortSelector.selectedIndex = 0;
+        this._updateOffscreenRows();
+    },
+
+    _sortByTimeline: function()
+    {
+        var selectedIndex = this._timelineSortSelector.selectedIndex;
+        if (!selectedIndex)
+            selectedIndex = 1; // Sort by start time by default.
+        var selectedOption = this._timelineSortSelector[selectedIndex];
+        var value = selectedOption.value;
+
+        var sortingFunction = this._sortingFunctions[value];
+        this._dataGrid.sortNodes(sortingFunction);
+        this.calculator = this._calculators[value];
+        if (this.calculator.startAtZero)
+            this._timelineGrid.hideEventDividers();
+        else
+            this._timelineGrid.showEventDividers();
+        this._dataGrid.markColumnAsSortedBy("timeline", "ascending");
+        this._updateOffscreenRows();
+    },
+
+    _createFilterStatusBarItems: function()
+    {
+        var filterBarElement = document.createElement("div");
+        filterBarElement.className = "scope-bar status-bar-item";
+        filterBarElement.id = "network-filter";
+
+        function createFilterElement(category, label)
+        {
+            var categoryElement = document.createElement("li");
+            categoryElement.category = category;
+            categoryElement.className = category;
+            categoryElement.appendChild(document.createTextNode(label));
+            categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
+            filterBarElement.appendChild(categoryElement);
+
+            return categoryElement;
+        }
+
+        this._filterAllElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));
+
+        // Add a divider
+        var dividerElement = document.createElement("div");
+        dividerElement.addStyleClass("scope-bar-divider");
+        filterBarElement.appendChild(dividerElement);
+
+        for (var category in this._categories)
+            createFilterElement.call(this, category, this._categories[category].title);
+        this._filterBarElement = filterBarElement;
+    },
+
+    _createSummaryBar: function()
+    {
+        this._summaryBarElement = document.createElement("div");
+        this._summaryBarElement.className = "network-summary-bar";
+        this.containerElement.appendChild(this._summaryBarElement);
+    },
+
+    _updateSummaryBar: function()
+    {
+        this._positionSummaryBar(); // Grid is growing.
+        var numRequests = this._resources.length;
+
+        if (!numRequests) {
+            if (this._summaryBarElement._isDisplayingWarning)
+                return;
+            this._summaryBarElement._isDisplayingWarning = true;
+
+            var img = document.createElement("img");
+            img.src = "Images/warningIcon.png";
+            this._summaryBarElement.removeChildren();
+            this._summaryBarElement.appendChild(img);
+            this._summaryBarElement.appendChild(document.createTextNode(" "));
+            this._summaryBarElement.appendChild(document.createTextNode(
+                WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity.")));
+            return;
+        }
+        delete this._summaryBarElement._isDisplayingWarning;
+
+        var transferSize = 0;
+        var baseTime = -1;
+        var maxTime = -1;
+        for (var i = 0; i < this._resources.length; ++i) {
+            var resource = this._resources[i];
+            transferSize += (resource.cached || !resource.transferSize) ? 0 : resource.transferSize;
+            if (resource.isMainResource)
+                baseTime = resource.startTime;
+            if (resource.endTime > maxTime)
+                maxTime = resource.endTime;
+        }
+        var text = String.sprintf(WebInspector.UIString("%d requests"), numRequests);
+        text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s transferred"), Number.bytesToString(transferSize));
+        if (baseTime !== -1 && this._mainResourceLoadTime !== -1 && this._mainResourceDOMContentTime !== -1 && this._mainResourceDOMContentTime > baseTime) {
+            text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"),
+                        Number.secondsToString(maxTime - baseTime),
+                        Number.secondsToString(this._mainResourceLoadTime - baseTime),
+                        Number.secondsToString(this._mainResourceDOMContentTime - baseTime));
+        }
+        this._summaryBarElement.textContent = text;
+    },
+
+    _showCategory: function(category)
+    {
+        this._dataGrid.element.addStyleClass("filter-" + category);
+        delete this._hiddenCategories[category];
+    },
+
+    _hideCategory: function(category)
+    {
+        this._dataGrid.element.removeStyleClass("filter-" + category);
+        this._hiddenCategories[category] = true;
+    },
+
+    _updateFilter: function(e)
+    {
+        var isMac = WebInspector.isMac();
+        var selectMultiple = false;
+        if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+        if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
+            selectMultiple = true;
+
+        this._filter(e.target, selectMultiple);
+        this._positionSummaryBar();
+    },
+
+    _filter: function(target, selectMultiple)
+    {
+        function unselectAll()
+        {
+            for (var i = 0; i < this._filterBarElement.childNodes.length; ++i) {
+                var child = this._filterBarElement.childNodes[i];
+                if (!child.category)
+                    continue;
+
+                child.removeStyleClass("selected");
+                this._hideCategory(child.category);
+            }
+        }
+
+        if (target.category === this._filterAllElement) {
+            if (target.hasStyleClass("selected")) {
+                // We can't unselect All, so we break early here
+                return;
+            }
+
+            // If All wasn't selected, and now is, unselect everything else.
+            unselectAll.call(this);
+        } else {
+            // Something other than All is being selected, so we want to unselect All.
+            if (this._filterAllElement.hasStyleClass("selected")) {
+                this._filterAllElement.removeStyleClass("selected");
+                this._hideCategory("all");
+            }
+        }
+
+        if (!selectMultiple) {
+            // If multiple selection is off, we want to unselect everything else
+            // and just select ourselves.
+            unselectAll.call(this);
+
+            target.addStyleClass("selected");
+            this._showCategory(target.category);
+            return;
+        }
+
+        if (target.hasStyleClass("selected")) {
+            // If selectMultiple is turned on, and we were selected, we just
+            // want to unselect ourselves.
+            target.removeStyleClass("selected");
+            this._hideCategory(target.category);
+        } else {
+            // If selectMultiple is turned on, and we weren't selected, we just
+            // want to select ourselves.
+            target.addStyleClass("selected");
+            this._showCategory(target.category);
+        }
+        this._updateOffscreenRows();
+    },
+
+    _scheduleRefresh: function()
+    {
+        if (this._needsRefresh)
+            return;
+
+        this._needsRefresh = true;
+
+        if (this.visible && !("_refreshTimeout" in this))
+            this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
+    },
+
+    _updateDividersIfNeeded: function(force)
+    {
+        var timelineColumn = this._dataGrid.columns.timeline;
+        for (var i = 0; i < this._dataGrid.resizers.length; ++i) {
+            if (timelineColumn.ordinal === this._dataGrid.resizers[i].rightNeighboringColumnID) {
+                // Position timline grid location.
+                this._timelineGrid.element.style.left = this._dataGrid.resizers[i].style.left;
+                this._timelineGrid.element.style.right = "18px";
+            }
+        }
+
+        var proceed = true;
+        if (!this.visible) {
+            this._scheduleRefresh();
+            proceed = false;
+        } else
+            proceed = this._timelineGrid.updateDividers(force, this.calculator);
+
+        if (!proceed)
+            return;
+
+        if (this.calculator.startAtZero || !this.calculator.computePercentageFromEventTime) {
+            // If our current sorting method starts at zero, that means it shows all
+            // resources starting at the same point, and so onLoad event and DOMContent
+            // event lines really wouldn't make much sense here, so don't render them.
+            // Additionally, if the calculator doesn't have the computePercentageFromEventTime
+            // function defined, we are probably sorting by size, and event times aren't relevant
+            // in this case.
+            return;
+        }
+
+        this._timelineGrid.removeEventDividers();
+        if (this._mainResourceLoadTime !== -1) {
+            var percent = this.calculator.computePercentageFromEventTime(this._mainResourceLoadTime);
+
+            var loadDivider = document.createElement("div");
+            loadDivider.className = "network-event-divider network-red-divider";
+
+            var loadDividerPadding = document.createElement("div");
+            loadDividerPadding.className = "network-event-divider-padding";
+            loadDividerPadding.title = WebInspector.UIString("Load event fired");
+            loadDividerPadding.appendChild(loadDivider);
+            loadDividerPadding.style.left = percent + "%";
+            this._timelineGrid.addEventDivider(loadDividerPadding);
+        }
+
+        if (this._mainResourceDOMContentTime !== -1) {
+            var percent = this.calculator.computePercentageFromEventTime(this._mainResourceDOMContentTime);
+
+            var domContentDivider = document.createElement("div");
+            domContentDivider.className = "network-event-divider network-blue-divider";
+
+            var domContentDividerPadding = document.createElement("div");
+            domContentDividerPadding.className = "network-event-divider-padding";
+            domContentDividerPadding.title = WebInspector.UIString("DOMContent event fired");
+            domContentDividerPadding.appendChild(domContentDivider);
+            domContentDividerPadding.style.left = percent + "%";
+            this._timelineGrid.addEventDivider(domContentDividerPadding);
+        }
+    },
+
+    _refreshIfNeeded: function()
+    {
+        if (this._needsRefresh)
+            this.refresh();
+    },
+
+    _invalidateAllItems: function()
+    {
+        this._staleResources = this._resources.slice();
+    },
+
+    get calculator()
+    {
+        return this._calculator;
+    },
+
+    set calculator(x)
+    {
+        if (!x || this._calculator === x)
+            return;
+
+        this._calculator = x;
+        this._calculator.reset();
+
+        this._invalidateAllItems();
+        this.refresh();
+    },
+
+    _resourceGridNode: function(resource)
+    {
+        return this._resourceGridNodes[resource.identifier];
+    },
+
+    revealAndSelectItem: function(resource)
+    {
+        var node = this._resourceGridNode(resource);
+        if (node) {
+            node.reveal();
+            node.select(true);
+        }
+    },
+
+    addEventDivider: function(divider)
+    {
+        this._timelineGrid.addEventDivider(divider);
+    },
+
+    _createStatusbarButtons: function()
+    {
+        this._preserveLogToggle = new WebInspector.StatusBarButton(WebInspector.UIString("Preserve Log upon Navigation"), "record-profile-status-bar-item");
+        this._preserveLogToggle.addEventListener("click", this._onPreserveLogClicked.bind(this), false);
+
+        this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
+        this._clearButton.addEventListener("click", this._reset.bind(this), false);
+
+        this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
+        this._largerResourcesButton.toggled = WebInspector.settings.resourcesLargeRows;
+        this._largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
+    },
+
+    set mainResourceLoadTime(x)
+    {
+        if (this._mainResourceLoadTime === x)
+            return;
+
+        this._mainResourceLoadTime = x || -1;
+        // Update the dividers to draw the new line
+        this._updateDividersIfNeeded(true);
+    },
+
+    set mainResourceDOMContentTime(x)
+    {
+        if (this._mainResourceDOMContentTime === x)
+            return;
+
+        this._mainResourceDOMContentTime = x || -1;
+        this._updateDividersIfNeeded(true);
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this._refreshIfNeeded();
+
+        if (this.visibleView)
+            this.visibleView.show(this._viewsContainerElement);
+
+        this._dataGrid.updateWidths();
+        this._positionSummaryBar();
+    },
+
+    hide: function()
+    {
+        WebInspector.Panel.prototype.hide.call(this);
+        this._popoverHelper.hidePopup();
+    },
+
+    get searchableViews()
+    {
+        var views = [];
+        return views;
+    },
+
+    searchMatchFound: function(view, matches)
+    {
+        this._resourceGridNode(view.resource).searchMatches = matches;
+    },
+
+    searchCanceled: function(startingNewSearch)
+    {
+        WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+        if (startingNewSearch || !this._resources)
+            return;
+    },
+
+    performSearch: function(query)
+    {
+        WebInspector.Panel.prototype.performSearch.call(this, query);
+    },
+
+    refresh: function()
+    {
+        this._needsRefresh = false;
+        if ("_refreshTimeout" in this) {
+            clearTimeout(this._refreshTimeout);
+            delete this._refreshTimeout;
+        }
+
+        var wasScrolledToLastRow = this._dataGrid.isScrolledToLastRow();
+        var staleItemsLength = this._staleResources.length;
+        var boundariesChanged = false;
+
+        for (var i = 0; i < staleItemsLength; ++i) {
+            var resource = this._staleResources[i];
+            var node = this._resourceGridNode(resource);
+            if (!node) {
+                // Create the timeline tree element and graph.
+                node = new WebInspector.NetworkDataGridNode(this, resource);
+                this._resourceGridNodes[resource.identifier] = node;
+                this._dataGrid.appendChild(node);
+            }
+            node.refreshResource();
+
+            if (this.calculator.updateBoundaries(resource))
+                boundariesChanged = true;
+        }
+
+        if (boundariesChanged) {
+            // The boundaries changed, so all item graphs are stale.
+            this._invalidateAllItems();
+            staleItemsLength = this._staleResources.length;
+        }
+
+        for (var i = 0; i < staleItemsLength; ++i)
+            this._resourceGridNode(this._staleResources[i]).refreshGraph(this.calculator);
+
+        this._staleResources = [];
+        this._sortItems();
+        this._updateSummaryBar();
+        this._dataGrid.updateWidths();
+
+        if (wasScrolledToLastRow)
+            this._dataGrid.scrollToLastRow();
+    },
+
+    _onPreserveLogClicked: function(e)
+    {
+        this._preserveLogToggle.toggled = !this._preserveLogToggle.toggled;
+    },
+
+    _reset: function()
+    {
+        this._popoverHelper.hidePopup();
+        this._closeVisibleResource();
+
+        this._toggleGridMode();
+
+        // Begin reset timeline
+        if (this._calculator)
+            this._calculator.reset();
+
+        this._resources = [];
+        this._resourcesById = {};
+        this._resourcesByURL = {};
+        this._staleResources = [];
+        this._resourceGridNodes = {};
+
+        this._dataGrid.removeChildren();
+        delete this._summaryBarRowNode;
+        this._updateDividersIfNeeded(true);
+        // End reset timeline.
+
+        this._mainResourceLoadTime = -1;
+        this._mainResourceDOMContentTime = -1;
+
+        this._viewsContainerElement.removeChildren();
+        this._viewsContainerElement.appendChild(this._closeButtonElement);
+        this._resetSummaryBar();
+    },
+
+    get resources()
+    {
+        return this._resources;
+    },
+
+    resourceById: function(id)
+    {
+        return this._resourcesById[id];
+    },
+
+    _onResourceStarted: function(event)
+    {
+        this._appendResource(event.data);
+    },
+
+    _appendResource: function(resource)
+    {
+        this._resources.push(resource);
+        this._resourcesById[resource.identifier] = resource;
+        this._resourcesByURL[resource.url] = resource;
+
+        // Pull all the redirects of the main resource upon commit load.
+        if (resource.redirects) {
+            for (var i = 0; i < resource.redirects.length; ++i)
+                this._refreshResource(resource.redirects[i]);
+        }
+
+        this._refreshResource(resource);
+    },
+
+    _onResourceUpdated: function(event)
+    {
+        this._refreshResource(event.data);
+    },
+
+    _refreshResource: function(resource)
+    {
+        this._staleResources.push(resource);
+        this._scheduleRefresh();
+
+        var oldView = WebInspector.ResourceView.existingResourceViewForResource(resource);
+        if (!oldView)
+            return;
+
+        if (WebInspector.ResourceView.resourceViewTypeMatchesResource(resource))
+            return;
+
+        var newView = WebInspector.ResourceView.recreateResourceView(resource);
+        if (this.visibleView === oldView)
+            this.visibleView = newView;
+    },
+
+    clear: function()
+    {
+        if (this._preserveLogToggle.toggled)
+            return;
+        this._reset();
+    },
+
+    _onMainResourceCommitLoad: function()
+    {
+        if (this._preserveLogToggle.toggled)
+            return;
+
+        this._reset();
+        // Now resurrect the main resource along with all redirects that lead to it.
+        var resourcesToAppend = (WebInspector.mainResource.redirects || []).concat(WebInspector.mainResource);
+        resourcesToAppend.forEach(this._appendResource, this);
+    },
+
+    canShowSourceLine: function(url, line)
+    {
+        return !!this._resourcesByURL[url];
+    },
+
+    showSourceLine: function(url, line)
+    {
+        this._showResource(this._resourcesByURL[url], line);
+    },
+
+    _showResource: function(resource, line)
+    {
+        if (!resource)
+            return;
+
+        this._popoverHelper.hidePopup();
+
+        this._toggleViewingResourceMode();
+
+        if (this.visibleView) {
+            this.visibleView.detach();
+            delete this.visibleView;
+        }
+
+        var view = new WebInspector.NetworkItemView(resource);
+        view.show(this._viewsContainerElement);
+        this.visibleView = view;
+
+        this.updateSidebarWidth();
+    },
+
+    _closeVisibleResource: function()
+    {
+        this.element.removeStyleClass("viewing-resource");
+
+        if (this.visibleView) {
+            this.visibleView.detach();
+            delete this.visibleView;
+        }
+
+        if (this._lastSelectedGraphTreeElement)
+            this._lastSelectedGraphTreeElement.select(true);
+
+        this.updateSidebarWidth();
+    },
+
+    _toggleLargerResources: function()
+    {
+        WebInspector.settings.resourcesLargeRows = !WebInspector.settings.resourcesLargeRows;
+        this._setLargerResources(WebInspector.settings.resourcesLargeRows);
+    },
+
+    _setLargerResources: function(enabled)
+    {
+        this._largerResourcesButton.toggled = enabled;
+        if (!enabled) {
+            this._largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
+            this._dataGrid.element.addStyleClass("small");
+            this._timelineGrid.element.addStyleClass("small");
+            this._viewsContainerElement.addStyleClass("small");
+        } else {
+            this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+            this._dataGrid.element.removeStyleClass("small");
+            this._timelineGrid.element.removeStyleClass("small");
+            this._viewsContainerElement.removeStyleClass("small");
+        }
+        this._positionSummaryBar();
+    },
+
+    _getPopoverAnchor: function(element)
+    {
+        var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label");
+        if (!anchor)
+            return null;
+        var resource = anchor.parentElement.resource;
+        return resource && resource.timing ? anchor : null;
+    },
+
+    _showPopover: function(anchor)
+    {
+        var resource = anchor.parentElement.resource;
+        var tableElement = WebInspector.ResourceTimingView.createTimingTable(resource);
+        var popover = new WebInspector.Popover(tableElement);
+        popover.show(anchor);
+        return popover;
+    },
+
+    _toggleGridMode: function()
+    {
+        if (this._viewingResourceMode) {
+            this._viewingResourceMode = false;
+            this.element.removeStyleClass("viewing-resource");
+            this._dataGrid.element.removeStyleClass("viewing-resource-mode");
+            this._viewsContainerElement.addStyleClass("hidden");
+            this.sidebarElement.style.right = 0;
+            this.sidebarElement.style.removeProperty("width");
+            if (this._dataGrid.selectedNode)
+                this._dataGrid.selectedNode.selected = false;
+        }
+
+        if (this._briefGrid) {
+            this._dataGrid.element.removeStyleClass("full-grid-mode");
+            this._dataGrid.element.addStyleClass("brief-grid-mode");
+
+            this._dataGrid.hideColumn("method");
+            this._dataGrid.hideColumn("status");
+            this._dataGrid.hideColumn("type");
+            this._dataGrid.hideColumn("size");
+            this._dataGrid.hideColumn("time");
+
+            var widths = {};
+            widths.name = 20;
+            widths.timeline = 80;
+        } else {
+            this._dataGrid.element.addStyleClass("full-grid-mode");
+            this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+            this._dataGrid.showColumn("method");
+            this._dataGrid.showColumn("status");
+            this._dataGrid.showColumn("type");
+            this._dataGrid.showColumn("size");
+            this._dataGrid.showColumn("time");
+
+            var widths = {};
+            widths.name = 20;
+            widths.method = 7;
+            widths.status = 8;
+            widths.type = 10;
+            widths.size = 10;
+            widths.time = 10;
+            widths.timeline = 37;
+        }
+
+        this._dataGrid.showColumn("timeline");
+        this._dataGrid.applyColumnWidthsMap(widths);
+
+    },
+
+    _toggleViewingResourceMode: function()
+    {
+        if (this._viewingResourceMode)
+            return;
+        this._viewingResourceMode = true;
+        this._preservedColumnWidths = this._dataGrid.columnWidthsMap();
+
+        this.element.addStyleClass("viewing-resource");
+        this._dataGrid.element.addStyleClass("viewing-resource-mode");
+        this._dataGrid.element.removeStyleClass("full-grid-mode");
+        this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+        this._dataGrid.hideColumn("method");
+        this._dataGrid.hideColumn("status");
+        this._dataGrid.hideColumn("type");
+        this._dataGrid.hideColumn("size");
+        this._dataGrid.hideColumn("time");
+        this._dataGrid.hideColumn("timeline");
+
+        this._viewsContainerElement.removeStyleClass("hidden");
+        this.updateSidebarWidth(200);
+
+        var widths = {};
+        widths.name = 100;
+        this._dataGrid.applyColumnWidthsMap(widths);
+    },
+
+    _contextMenu: function(event)
+    {
+        // createBlobURL is enabled conditionally, do not expose resource export if it's not available.
+        if (typeof window.webkitURL.createObjectURL !== "function" || !Preferences.resourceExportEnabled)
+            return;
+
+        var contextMenu = new WebInspector.ContextMenu();
+        var gridNode = this._dataGrid.dataGridNodeFromNode(event.target);
+        var resource = gridNode && gridNode._resource;
+        if (resource)
+            contextMenu.appendItem(WebInspector.UIString("Export to HAR"), this._exportResource.bind(this, resource));
+        contextMenu.appendItem(WebInspector.UIString("Export all to HAR"), this._exportAll.bind(this));
+        contextMenu.show(event);
+    },
+
+    _exportAll: function()
+    {
+        var harArchive = {
+            log: (new WebInspector.HARLog()).build()
+        }
+        InspectorFrontendHost.copyText(JSON.stringify(harArchive));
+    },
+
+    _exportResource: function(resource)
+    {
+        var har = (new WebInspector.HAREntry(resource)).build();
+        InspectorFrontendHost.copyText(JSON.stringify(har));
+    },
+
+    _updateOffscreenRows: function(e)
+    {
+        var dataTableBody = this._dataGrid.dataTableBody;
+        var rows = dataTableBody.children;
+        var recordsCount = rows.length;
+        if (recordsCount < 2)
+            return;  // Filler row only.
+
+        var visibleTop = this._dataGrid.scrollContainer.scrollTop;
+        var visibleBottom = visibleTop + this._dataGrid.scrollContainer.offsetHeight;
+
+        var rowHeight = 0;
+
+        // Filler is at recordsCount - 1.
+        var unfilteredRowIndex = 0;
+        for (var i = 0; i < recordsCount - 1; ++i) {
+            var row = rows[i];
+            // Don't touch summaty - quit instead.
+            if (this._summaryBarRowNode && row === this._summaryBarRowNode.element)
+                break;
+
+            var dataGridNode = this._dataGrid.dataGridNodeFromNode(row);
+            if (dataGridNode.isFilteredOut()) {
+                row.removeStyleClass("offscreen");
+                continue;
+            }
+
+            if (!rowHeight)
+                rowHeight = row.offsetHeight;
+
+            var rowIsVisible = unfilteredRowIndex * rowHeight < visibleBottom && (unfilteredRowIndex + 1) * rowHeight > visibleTop;
+            if (rowIsVisible !== row.rowIsVisible) {
+                if (rowIsVisible)
+                    row.removeStyleClass("offscreen");
+                else
+                    row.addStyleClass("offscreen");
+                row.rowIsVisible = rowIsVisible;
+            }
+            unfilteredRowIndex++;
+        }
+    }
+}
+
+WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.NetworkBaseCalculator = function()
+{
+}
+
+WebInspector.NetworkBaseCalculator.prototype = {
+    computeSummaryValues: function(items)
+    {
+        var total = 0;
+        var categoryValues = {};
+
+        var itemsLength = items.length;
+        for (var i = 0; i < itemsLength; ++i) {
+            var item = items[i];
+            var value = this._value(item);
+            if (typeof value === "undefined")
+                continue;
+            if (!(item.category.name in categoryValues))
+                categoryValues[item.category.name] = 0;
+            categoryValues[item.category.name] += value;
+            total += value;
+        }
+
+        return {categoryValues: categoryValues, total: total};
+    },
+
+    computeBarGraphPercentages: function(item)
+    {
+        return {start: 0, middle: 0, end: (this._value(item) / this.boundarySpan) * 100};
+    },
+
+    computeBarGraphLabels: function(item)
+    {
+        const label = this.formatValue(this._value(item));
+        return {left: label, right: label, tooltip: label};
+    },
+
+    get boundarySpan()
+    {
+        return this.maximumBoundary - this.minimumBoundary;
+    },
+
+    updateBoundaries: function(item)
+    {
+        this.minimumBoundary = 0;
+
+        var value = this._value(item);
+        if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) {
+            this.maximumBoundary = value;
+            return true;
+        }
+        return false;
+    },
+
+    reset: function()
+    {
+        delete this.minimumBoundary;
+        delete this.maximumBoundary;
+    },
+
+    _value: function(item)
+    {
+        return 0;
+    },
+
+    formatValue: function(value)
+    {
+        return value.toString();
+    }
+}
+
+WebInspector.NetworkTimeCalculator = function(startAtZero)
+{
+    WebInspector.NetworkBaseCalculator.call(this);
+    this.startAtZero = startAtZero;
+}
+
+WebInspector.NetworkTimeCalculator.prototype = {
+    computeSummaryValues: function(resources)
+    {
+        var resourcesByCategory = {};
+        var resourcesLength = resources.length;
+        for (var i = 0; i < resourcesLength; ++i) {
+            var resource = resources[i];
+            if (!(resource.category.name in resourcesByCategory))
+                resourcesByCategory[resource.category.name] = [];
+            resourcesByCategory[resource.category.name].push(resource);
+        }
+
+        var earliestStart;
+        var latestEnd;
+        var categoryValues = {};
+        for (var category in resourcesByCategory) {
+            resourcesByCategory[category].sort(WebInspector.Resource.CompareByTime);
+            categoryValues[category] = 0;
+
+            var segment = {start: -1, end: -1};
+
+            var categoryResources = resourcesByCategory[category];
+            var resourcesLength = categoryResources.length;
+            for (var i = 0; i < resourcesLength; ++i) {
+                var resource = categoryResources[i];
+                if (resource.startTime === -1 || resource.endTime === -1)
+                    continue;
+
+                if (typeof earliestStart === "undefined")
+                    earliestStart = resource.startTime;
+                else
+                    earliestStart = Math.min(earliestStart, resource.startTime);
+
+                if (typeof latestEnd === "undefined")
+                    latestEnd = resource.endTime;
+                else
+                    latestEnd = Math.max(latestEnd, resource.endTime);
+
+                if (resource.startTime <= segment.end) {
+                    segment.end = Math.max(segment.end, resource.endTime);
+                    continue;
+                }
+
+                categoryValues[category] += segment.end - segment.start;
+
+                segment.start = resource.startTime;
+                segment.end = resource.endTime;
+            }
+
+            // Add the last segment
+            categoryValues[category] += segment.end - segment.start;
+        }
+
+        return {categoryValues: categoryValues, total: latestEnd - earliestStart};
+    },
+
+    computeBarGraphPercentages: function(resource)
+    {
+        if (resource.startTime !== -1)
+            var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var start = 0;
+
+        if (resource.responseReceivedTime !== -1)
+            var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var middle = (this.startAtZero ? start : 100);
+
+        if (resource.endTime !== -1)
+            var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100;
+        else
+            var end = (this.startAtZero ? middle : 100);
+
+        if (this.startAtZero) {
+            end -= start;
+            middle -= start;
+            start = 0;
+        }
+
+        return {start: start, middle: middle, end: end};
+    },
+
+    computePercentageFromEventTime: function(eventTime)
+    {
+        // This function computes a percentage in terms of the total loading time
+        // of a specific event. If startAtZero is set, then this is useless, and we
+        // want to return 0.
+        if (eventTime !== -1 && !this.startAtZero)
+            return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100;
+
+        return 0;
+    },
+
+    computeBarGraphLabels: function(resource)
+    {
+        var rightLabel = "";
+        if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
+            rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime);
+
+        var hasLatency = resource.latency > 0;
+        if (hasLatency)
+            var leftLabel = this.formatValue(resource.latency);
+        else
+            var leftLabel = rightLabel;
+
+        if (resource.timing)
+            return {left: leftLabel, right: rightLabel};
+
+        if (hasLatency && rightLabel) {
+            var total = this.formatValue(resource.duration);
+            var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total);
+        } else if (hasLatency)
+            var tooltip = WebInspector.UIString("%s latency", leftLabel);
+        else if (rightLabel)
+            var tooltip = WebInspector.UIString("%s download", rightLabel);
+
+        if (resource.cached)
+            tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+        return {left: leftLabel, right: rightLabel, tooltip: tooltip};
+    },
+
+    updateBoundaries: function(resource)
+    {
+        var didChange = false;
+
+        var lowerBound;
+        if (this.startAtZero)
+            lowerBound = 0;
+        else
+            lowerBound = this._lowerBound(resource);
+
+        if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
+            this.minimumBoundary = lowerBound;
+            didChange = true;
+        }
+
+        var upperBound = this._upperBound(resource);
+        if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
+            this.maximumBoundary = upperBound;
+            didChange = true;
+        }
+
+        return didChange;
+    },
+
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _lowerBound: function(resource)
+    {
+        return 0;
+    },
+
+    _upperBound: function(resource)
+    {
+        return 0;
+    }
+}
+
+WebInspector.NetworkTimeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype;
+
+WebInspector.NetworkTransferTimeCalculator = function()
+{
+    WebInspector.NetworkTimeCalculator.call(this, false);
+}
+
+WebInspector.NetworkTransferTimeCalculator.prototype = {
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _lowerBound: function(resource)
+    {
+        return resource.startTime;
+    },
+
+    _upperBound: function(resource)
+    {
+        return resource.endTime;
+    }
+}
+
+WebInspector.NetworkTransferTimeCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;
+
+WebInspector.NetworkTransferDurationCalculator = function()
+{
+    WebInspector.NetworkTimeCalculator.call(this, true);
+}
+
+WebInspector.NetworkTransferDurationCalculator.prototype = {
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    },
+
+    _upperBound: function(resource)
+    {
+        return resource.duration;
+    }
+}
+
+WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;
+
+WebInspector.NetworkDataGridNode = function(panel, resource)
+{
+    WebInspector.DataGridNode.call(this, {});
+    this._panel = panel;
+    this._resource = resource;
+}
+
+WebInspector.NetworkDataGridNode.prototype = {
+    createCells: function()
+    {
+        this._nameCell = this._createDivInTD("name");
+        this._methodCell = this._createDivInTD("method");
+        this._statusCell = this._createDivInTD("status");
+        this._typeCell = this._createDivInTD("type");
+        this._sizeCell = this._createDivInTD("size");
+        this._timeCell = this._createDivInTD("time");
+        this._createTimelineCell();
+        this._nameCell.addEventListener("click", this.select.bind(this), false);
+        this._nameCell.addEventListener("dblclick", this._openInNewTab.bind(this), false);
+    },
+
+    isFilteredOut: function()
+    {
+        if (!this._panel._hiddenCategories.all)
+            return false;
+        return this._resource.category.name in this._panel._hiddenCategories;
+    },
+
+    select: function()
+    {
+        this._panel._showResource(this._resource);
+        WebInspector.DataGridNode.prototype.select.apply(this, arguments);
+    },
+
+    _openInNewTab: function()
+    {
+        InspectorBackend.openInInspectedWindow(this._resource.url);
+    },
+
+    get selectable()
+    {
+        if (!this._panel._viewingResourceMode)
+            return false;
+        return !this.isFilteredOut();
+    },
+
+    _createDivInTD: function(columnIdentifier)
+    {
+        var td = document.createElement("td");
+        td.className = columnIdentifier + "-column";
+        var div = document.createElement("div");
+        td.appendChild(div);
+        this._element.appendChild(td);
+        return div;
+    },
+
+    _createTimelineCell: function()
+    {
+        this._graphElement = document.createElement("div");
+        this._graphElement.className = "network-graph-side";
+
+        this._barAreaElement = document.createElement("div");
+        //    this._barAreaElement.className = "network-graph-bar-area hidden";
+        this._barAreaElement.className = "network-graph-bar-area";
+        this._barAreaElement.resource = this._resource;
+        this._graphElement.appendChild(this._barAreaElement);
+
+        this._barLeftElement = document.createElement("div");
+        this._barLeftElement.className = "network-graph-bar waiting";
+        this._barAreaElement.appendChild(this._barLeftElement);
+
+        this._barRightElement = document.createElement("div");
+        this._barRightElement.className = "network-graph-bar";
+        this._barAreaElement.appendChild(this._barRightElement);
+
+
+        this._labelLeftElement = document.createElement("div");
+        this._labelLeftElement.className = "network-graph-label waiting";
+        this._barAreaElement.appendChild(this._labelLeftElement);
+
+        this._labelRightElement = document.createElement("div");
+        this._labelRightElement.className = "network-graph-label";
+        this._barAreaElement.appendChild(this._labelRightElement);
+
+        this._graphElement.addEventListener("mouseover", this._refreshLabelPositions.bind(this), false);
+
+        this._timelineCell = document.createElement("td");
+        this._timelineCell.className = "timeline-column";
+        this._element.appendChild(this._timelineCell);
+        this._timelineCell.appendChild(this._graphElement);
+    },
+
+    refreshResource: function()
+    {
+        this._refreshNameCell();
+
+        this._methodCell.textContent = this._resource.requestMethod;
+
+        this._refreshStatusCell();
+
+        if (this._resource.mimeType) {
+            this._typeCell.removeStyleClass("network-dim-cell");
+            this._typeCell.textContent = this._resource.mimeType;
+        } else {
+            this._typeCell.addStyleClass("network-dim-cell");
+            this._typeCell.textContent = WebInspector.UIString("Pending");
+        }
+
+        this._refreshSizeCell();
+        this._refreshTimeCell();
+
+        if (this._resource.cached)
+            this._graphElement.addStyleClass("resource-cached");
+
+        this._element.addStyleClass("network-item");
+        if (!this._element.hasStyleClass("network-category-" + this._resource.category.name)) {
+            this._element.removeMatchingStyleClasses("network-category-\\w+");
+            this._element.addStyleClass("network-category-" + this._resource.category.name);
+        }
+    },
+
+    _refreshNameCell: function()
+    {
+        this._nameCell.removeChildren();
+
+        if (this._resource.category === WebInspector.resourceCategories.images) {
+            var previewImage = document.createElement("img");
+            previewImage.className = "image-network-icon-preview";
+            this._resource.populateImageSource(previewImage);
+
+            var iconElement = document.createElement("div");
+            iconElement.className = "icon";
+            iconElement.appendChild(previewImage);
+        } else {
+            var iconElement = document.createElement("img");
+            iconElement.className = "icon";
+        }
+        this._nameCell.appendChild(iconElement);
+        this._nameCell.appendChild(document.createTextNode(this._fileName()));
+
+
+        var subtitle = this._resource.displayDomain;
+
+        if (this._resource.path && this._resource.lastPathComponent) {
+            var lastPathComponentIndex = this._resource.path.lastIndexOf("/" + this._resource.lastPathComponent);
+            if (lastPathComponentIndex != -1)
+                subtitle += this._resource.path.substring(0, lastPathComponentIndex);
+        }
+
+        this._appendSubtitle(this._nameCell, subtitle);
+        this._nameCell.title = this._resource.url;
+    },
+
+    _fileName: function()
+    {
+        var fileName = this._resource.displayName;
+        if (this._resource.queryString)
+            fileName += "?" + this._resource.queryString;
+        return fileName;
+    },
+
+    _refreshStatusCell: function()
+    {
+        this._statusCell.removeChildren();
+
+        var fromCache = this._resource.cached;
+        if (fromCache) {
+            this._statusCell.textContent = WebInspector.UIString("(from cache)");
+            this._statusCell.addStyleClass("network-dim-cell");
+            return;
+        }
+
+        this._statusCell.removeStyleClass("network-dim-cell");
+        if (this._resource.statusCode) {
+            this._statusCell.appendChild(document.createTextNode(this._resource.statusCode));
+            this._statusCell.removeStyleClass("network-dim-cell");
+            this._appendSubtitle(this._statusCell, this._resource.statusText);
+            this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText;
+        } else {
+            this._statusCell.addStyleClass("network-dim-cell");
+            this._statusCell.textContent = WebInspector.UIString("Pending");
+        }
+    },
+
+    _refreshSizeCell: function()
+    {
+        var resourceSize = typeof this._resource.resourceSize === "number" ? Number.bytesToString(this._resource.resourceSize) : "?";
+        var transferSize = typeof this._resource.transferSize === "number" ? Number.bytesToString(this._resource.transferSize) : "?";
+        var fromCache = this._resource.cached;
+        this._sizeCell.textContent = !fromCache ? resourceSize : WebInspector.UIString("(from cache)");
+        if (fromCache)
+            this._sizeCell.addStyleClass("network-dim-cell");
+        else
+            this._sizeCell.removeStyleClass("network-dim-cell");
+        if (!fromCache)
+            this._appendSubtitle(this._sizeCell, transferSize);
+    },
+
+    _refreshTimeCell: function()
+    {
+        if (this._resource.duration > 0) {
+            this._timeCell.removeStyleClass("network-dim-cell");
+            this._timeCell.textContent = Number.secondsToString(this._resource.duration);
+            this._appendSubtitle(this._timeCell, Number.secondsToString(this._resource.latency));
+        } else {
+            this._timeCell.addStyleClass("network-dim-cell");
+            this._timeCell.textContent = WebInspector.UIString("Pending");
+        }
+    },
+
+    _appendSubtitle: function(cellElement, subtitleText)
+    {
+        var subtitleElement = document.createElement("div");
+        subtitleElement.className = "network-cell-subtitle";
+        subtitleElement.textContent = subtitleText;
+        cellElement.appendChild(subtitleElement);
+    },
+
+    refreshGraph: function(calculator)
+    {
+        var percentages = calculator.computeBarGraphPercentages(this._resource);
+        this._percentages = percentages;
+
+        this._barAreaElement.removeStyleClass("hidden");
+
+        if (!this._graphElement.hasStyleClass("network-category-" + this._resource.category.name)) {
+            this._graphElement.removeMatchingStyleClasses("network-category-\\w+");
+            this._graphElement.addStyleClass("network-category-" + this._resource.category.name);
+        }
+
+        this._barLeftElement.style.setProperty("left", percentages.start + "%");
+        this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+        this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
+        this._barRightElement.style.setProperty("left", percentages.middle + "%");
+
+        var labels = calculator.computeBarGraphLabels(this._resource);
+        this._labelLeftElement.textContent = labels.left;
+        this._labelRightElement.textContent = labels.right;
+
+        var tooltip = (labels.tooltip || "");
+        this._barLeftElement.title = tooltip;
+        this._labelLeftElement.title = tooltip;
+        this._labelRightElement.title = tooltip;
+        this._barRightElement.title = tooltip;
+    },
+
+    _refreshLabelPositions: function()
+    {
+        if (!this._percentages)
+            return;
+        this._labelLeftElement.style.removeProperty("left");
+        this._labelLeftElement.style.removeProperty("right");
+        this._labelLeftElement.removeStyleClass("before");
+        this._labelLeftElement.removeStyleClass("hidden");
+
+        this._labelRightElement.style.removeProperty("left");
+        this._labelRightElement.style.removeProperty("right");
+        this._labelRightElement.removeStyleClass("after");
+        this._labelRightElement.removeStyleClass("hidden");
+
+        const labelPadding = 10;
+        const barRightElementOffsetWidth = this._barRightElement.offsetWidth;
+        const barLeftElementOffsetWidth = this._barLeftElement.offsetWidth;
+
+        if (this._barLeftElement) {
+            var leftBarWidth = barLeftElementOffsetWidth - labelPadding;
+            var rightBarWidth = (barRightElementOffsetWidth - barLeftElementOffsetWidth) - labelPadding;
+        } else {
+            var leftBarWidth = (barLeftElementOffsetWidth - barRightElementOffsetWidth) - labelPadding;
+            var rightBarWidth = barRightElementOffsetWidth - labelPadding;
+        }
+
+        const labelLeftElementOffsetWidth = this._labelLeftElement.offsetWidth;
+        const labelRightElementOffsetWidth = this._labelRightElement.offsetWidth;
+
+        const labelBefore = (labelLeftElementOffsetWidth > leftBarWidth);
+        const labelAfter = (labelRightElementOffsetWidth > rightBarWidth);
+        const graphElementOffsetWidth = this._graphElement.offsetWidth;
+
+        if (labelBefore && (graphElementOffsetWidth * (this._percentages.start / 100)) < (labelLeftElementOffsetWidth + 10))
+            var leftHidden = true;
+
+        if (labelAfter && (graphElementOffsetWidth * ((100 - this._percentages.end) / 100)) < (labelRightElementOffsetWidth + 10))
+            var rightHidden = true;
+
+        if (barLeftElementOffsetWidth == barRightElementOffsetWidth) {
+            // The left/right label data are the same, so a before/after label can be replaced by an on-bar label.
+            if (labelBefore && !labelAfter)
+                leftHidden = true;
+            else if (labelAfter && !labelBefore)
+                rightHidden = true;
+        }
+
+        if (labelBefore) {
+            if (leftHidden)
+                this._labelLeftElement.addStyleClass("hidden");
+            this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%");
+            this._labelLeftElement.addStyleClass("before");
+        } else {
+            this._labelLeftElement.style.setProperty("left", this._percentages.start + "%");
+            this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%");
+        }
+
+        if (labelAfter) {
+            if (rightHidden)
+                this._labelRightElement.addStyleClass("hidden");
+            this._labelRightElement.style.setProperty("left", this._percentages.end + "%");
+            this._labelRightElement.addStyleClass("after");
+        } else {
+            this._labelRightElement.style.setProperty("left", this._percentages.middle + "%");
+            this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%");
+        }
+    }
+}
+
+WebInspector.NetworkDataGridNode.NameComparator = function(a, b)
+{
+    var aFileName = a._resource.displayName + (a._resource.queryString ? a._resource.queryString : "");
+    var bFileName = b._resource.displayName + (b._resource.queryString ? b._resource.queryString : "");
+    if (aFileName > bFileName)
+        return 1;
+    if (bFileName > aFileName)
+        return -1;
+    return 0;
+}
+
+WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
+{
+    if (b._resource.cached && !a._resource.cached)
+        return 1;
+    if (a._resource.cached && !b._resource.cached)
+        return -1;
+
+    if (a._resource.resourceSize === b._resource.resourceSize)
+        return 0;
+
+    return a._resource.resourceSize - b._resource.resourceSize;
+}
+
+WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, revert, a, b)
+{
+    var aValue = a._resource[propertyName];
+    var bValue = b._resource[propertyName];
+    if (aValue > bValue)
+        return revert ? -1 : 1;
+    if (bValue > aValue)
+        return revert ? 1 : -1;
+    return 0;
+}
+
+WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.NetworkTotalGridNode = function(element)
+{
+    this._summaryBarElement = element;
+    WebInspector.DataGridNode.call(this, {summaryRow: true});
+}
+
+WebInspector.NetworkTotalGridNode.prototype = {
+    isFilteredOut: function()
+    {
+        return false;
+    },
+
+    get selectable()
+    {
+        return false;
+    },
+
+    createCells: function()
+    {
+        var td = document.createElement("td");
+        td.setAttribute("colspan", 7);
+        td.className = "network-summary";
+        td.appendChild(this._summaryBarElement);
+        this._element.appendChild(td);
+    }
+}
+
+WebInspector.NetworkTotalGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js
new file mode 100644
index 0000000..5872b8b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Object.js
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Object = function() {
+}
+
+WebInspector.Object.prototype = {
+    addEventListener: function(eventType, listener, thisObject)
+    {
+        if (!("_listeners" in this))
+            this._listeners = {};
+        if (!(eventType in this._listeners))
+            this._listeners[eventType] = [];
+        this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
+    },
+
+    removeEventListener: function(eventType, listener, thisObject)
+    {
+        if (!("_listeners" in this) || !(eventType in this._listeners))
+            return;
+        var listeners = this._listeners[eventType];
+        for (var i = 0; i < listeners.length; ++i) {
+            if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+                listeners.splice(i, 1);
+            else if (!listener && thisObject && listeners[i].thisObject === thisObject)
+                listeners.splice(i, 1);
+        }
+
+        if (!listeners.length)
+            delete this._listeners[eventType];
+    },
+
+    removeAllListeners: function()
+    {
+        delete this._listeners;
+    },
+
+    dispatchEventToListeners: function(eventType, eventData)
+    {
+        if (!("_listeners" in this) || !(eventType in this._listeners))
+            return;
+
+        var stoppedPropagation = false;
+
+        function stopPropagation()
+        {
+            stoppedPropagation = true;
+        }
+
+        function preventDefault()
+        {
+            this.defaultPrevented = true;
+        }
+
+        var event = {target: this, type: eventType, data: eventData, defaultPrevented: false};
+        event.stopPropagation = stopPropagation;
+        event.preventDefault = preventDefault;
+
+        var listeners = this._listeners[eventType].slice(0);
+        for (var i = 0; i < listeners.length; ++i) {
+            listeners[i].listener.call(listeners[i].thisObject, event);
+            if (stoppedPropagation)
+                break;
+        }
+
+        return event.defaultPrevented;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js
new file mode 100644
index 0000000..88fddd6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
+{
+    this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
+    this.object = object;
+    this.ignoreHasOwnProperty = ignoreHasOwnProperty;
+    this.extraProperties = extraProperties;
+    this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
+    this.editable = true;
+
+    WebInspector.PropertiesSection.call(this, title, subtitle);
+}
+
+WebInspector.ObjectPropertiesSection.prototype = {
+    onpopulate: function()
+    {
+        this.update();
+    },
+
+    update: function()
+    {
+        var self = this;
+        var callback = function(properties) {
+            if (!properties)
+                return;
+            self.updateProperties(properties);
+        };
+        this.object.getProperties(this.ignoreHasOwnProperty, true, callback);
+    },
+
+    updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer)
+    {
+        if (!rootTreeElementConstructor)
+            rootTreeElementConstructor = this.treeElementConstructor;
+            
+        if (!rootPropertyComparer)
+            rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties;
+            
+        if (this.extraProperties)
+            for (var i = 0; i < this.extraProperties.length; ++i)
+                properties.push(this.extraProperties[i]);
+                
+        properties.sort(rootPropertyComparer);
+
+        this.propertiesTreeOutline.removeChildren();
+
+        for (var i = 0; i < properties.length; ++i) {
+            properties[i].parentObject = this.object;
+            this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i]));
+        }
+
+        if (!this.propertiesTreeOutline.children.length) {
+            var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
+            var infoElement = new TreeElement(null, null, false);
+            infoElement.titleHTML = title;
+            this.propertiesTreeOutline.appendChild(infoElement);
+        }
+        this.propertiesForTest = properties;
+    }
+}
+
+WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) 
+{
+    var a = propertyA.name;
+    var b = propertyB.name;
+    if (a === "__proto__")
+        return 1;
+    if (b === "__proto__")
+        return -1;
+
+    // if used elsewhere make sure to
+    //  - convert a and b to strings (not needed here, properties are all strings)
+    //  - check if a == b (not needed here, no two properties can be the same)
+
+    var diff = 0;
+    var chunk = /^\d+|^\D+/;
+    var chunka, chunkb, anum, bnum;
+    while (diff === 0) {
+        if (!a && b)
+            return -1;
+        if (!b && a)
+            return 1;
+        chunka = a.match(chunk)[0];
+        chunkb = b.match(chunk)[0];
+        anum = !isNaN(chunka);
+        bnum = !isNaN(chunkb);
+        if (anum && !bnum)
+            return -1;
+        if (bnum && !anum)
+            return 1;
+        if (anum && bnum) {
+            diff = chunka - chunkb;
+            if (diff === 0 && chunka.length !== chunkb.length) {
+                if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
+                    return chunka.length - chunkb.length;
+                else
+                    return chunkb.length - chunka.length;
+            }
+        } else if (chunka !== chunkb)
+            return (chunka < chunkb) ? -1 : 1;
+        a = a.substring(chunka.length);
+        b = b.substring(chunkb.length);
+    }
+    return diff;
+}
+
+WebInspector.ObjectPropertyTreeElement = function(property)
+{
+    this.property = property;
+
+    // Pass an empty title, the title gets made later in onattach.
+    TreeElement.call(this, "", null, false);
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype = {
+    onpopulate: function()
+    {
+        if (this.children.length && !this.shouldRefreshChildren)
+            return;
+
+        var callback = function(properties) {
+            this.removeChildren();
+            if (!properties)
+                return;
+
+            properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
+            for (var i = 0; i < properties.length; ++i) {
+                this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
+            }
+        };
+        this.property.value.getOwnProperties(true, callback.bind(this));
+    },
+
+    ondblclick: function(event)
+    {
+        this.startEditing();
+    },
+
+    onattach: function()
+    {
+        this.update();
+    },
+
+    update: function()
+    {
+        this.nameElement = document.createElement("span");
+        this.nameElement.className = "name";
+        this.nameElement.textContent = this.property.name;
+
+        var separatorElement = document.createElement("span");
+        separatorElement.className = "separator";
+        separatorElement.textContent = ": ";
+        
+        this.valueElement = document.createElement("span");
+        this.valueElement.className = "value";
+
+        var description = this.property.value.description;
+        // Render \n as a nice unicode cr symbol.
+        if (this.property.value.type === "string" && typeof description === "string")
+            description = description.replace(/\n/g, "\u21B5");
+        this.valueElement.textContent = description;
+
+        if (this.property.isGetter)
+            this.valueElement.addStyleClass("dimmed");
+        if (this.property.value.isError())
+            this.valueElement.addStyleClass("error");
+        if (this.property.value.type)
+            this.valueElement.addStyleClass("console-formatted-" + this.property.value.type);
+        if (this.property.value.type === "node")
+            this.valueElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false);
+
+        this.listItemElement.removeChildren();
+
+        this.listItemElement.appendChild(this.nameElement);
+        this.listItemElement.appendChild(separatorElement);
+        this.listItemElement.appendChild(this.valueElement);
+        this.hasChildren = this.property.value.hasChildren;
+    },
+
+    _contextMenuEventFired: function()
+    {
+        function selectNode(nodeId)
+        {
+            if (nodeId) {
+                WebInspector.panels.elements.switchToAndFocus(WebInspector.domAgent.nodeForId(nodeId));
+            }
+        }
+
+        function revealElement()
+        {
+            this.property.value.pushNodeToFrontend(selectNode);
+        }
+
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this));
+        contextMenu.show(event);
+    },
+
+    updateSiblings: function()
+    {
+        if (this.parent.root)
+            this.treeOutline.section.update();
+        else
+            this.parent.shouldRefreshChildren = true;
+    },
+
+    startEditing: function()
+    {
+        if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
+            return;
+
+        var context = { expanded: this.expanded };
+
+        // Lie about our children to prevent expanding on double click and to collapse subproperties.
+        this.hasChildren = false;
+
+        this.listItemElement.addStyleClass("editing-sub-part");
+
+        WebInspector.startEditing(this.valueElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
+    },
+
+    editingEnded: function(context)
+    {
+        this.listItemElement.scrollLeft = 0;
+        this.listItemElement.removeStyleClass("editing-sub-part");
+        if (context.expanded)
+            this.expand();
+    },
+
+    editingCancelled: function(element, context)
+    {
+        this.update();
+        this.editingEnded(context);
+    },
+
+    editingCommitted: function(element, userInput, previousContent, context)
+    {
+        if (userInput === previousContent)
+            return this.editingCancelled(element, context); // nothing changed, so cancel
+
+        this.applyExpression(userInput, true);
+
+        this.editingEnded(context);
+    },
+
+    applyExpression: function(expression, updateInterface)
+    {
+        expression = expression.trim();
+        var expressionLength = expression.length;
+        var self = this;
+        var callback = function(success) {
+            if (!updateInterface)
+                return;
+
+            if (!success)
+                self.update();
+
+            if (!expressionLength) {
+                // The property was deleted, so remove this tree element.
+                self.parent.removeChild(this);
+            } else {
+                // Call updateSiblings since their value might be based on the value that just changed.
+                self.updateSiblings();
+            }
+        };
+        this.property.parentObject.setPropertyValue(this.property.name, expression.trim(), callback);
+    }
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Panel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Panel.js
new file mode 100644
index 0000000..4c42a60
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Panel.js
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Panel = function(name)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("panel");
+    this.element.addStyleClass(name);
+    this._panelName = name;
+
+    WebInspector.settings.installApplicationSetting(this._sidebarWidthSettingName(), undefined);
+}
+
+// Should by in sync with style declarations.
+WebInspector.Panel.counterRightMargin = 25;
+
+WebInspector.Panel.prototype = {
+    get toolbarItem()
+    {
+        if (this._toolbarItem)
+            return this._toolbarItem;
+
+        // Sample toolbar item as markup:
+        // <button class="toolbar-item resources toggleable">
+        // <div class="toolbar-icon"></div>
+        // <div class="toolbar-label">Resources</div>
+        // </button>
+
+        this._toolbarItem = document.createElement("button");
+        this._toolbarItem.className = "toolbar-item toggleable";
+        this._toolbarItem.panel = this;
+
+        this._toolbarItem.addStyleClass(this._panelName);
+
+        var iconElement = document.createElement("div");
+        iconElement.className = "toolbar-icon";
+        this._toolbarItem.appendChild(iconElement);
+
+        if ("toolbarItemLabel" in this) {
+            var labelElement = document.createElement("div");
+            labelElement.className = "toolbar-label";
+            labelElement.textContent = this.toolbarItemLabel;
+            this._toolbarItem.appendChild(labelElement);
+        }
+
+        return this._toolbarItem;
+    },
+
+    get name()
+    {
+        return this._panelName;
+    },
+
+    show: function()
+    {
+        WebInspector.View.prototype.show.call(this);
+
+        var statusBarItems = this.statusBarItems;
+        if (statusBarItems) {
+            this._statusBarItemContainer = document.createElement("div");
+            for (var i = 0; i < statusBarItems.length; ++i)
+                this._statusBarItemContainer.appendChild(statusBarItems[i]);
+            document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer);
+        }
+
+        if ("_toolbarItem" in this)
+            this._toolbarItem.addStyleClass("toggled-on");
+
+        WebInspector.currentFocusElement = this.defaultFocusedElement;
+
+        this.restoreSidebarWidth();
+        this._restoreScrollPositions();
+    },
+
+    hide: function()
+    {
+        this._storeScrollPositions();
+        WebInspector.View.prototype.hide.call(this);
+
+        if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode)
+            this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer);
+        delete this._statusBarItemContainer;
+        if ("_toolbarItem" in this)
+            this._toolbarItem.removeStyleClass("toggled-on");
+    },
+
+    get defaultFocusedElement()
+    {
+        return this.sidebarTreeElement || this.element;
+    },
+
+    attach: function()
+    {
+        if (!this.element.parentNode)
+            document.getElementById("main-panels").appendChild(this.element);
+    },
+
+    searchCanceled: function()
+    {
+        if (this._searchResults) {
+            for (var i = 0; i < this._searchResults.length; ++i) {
+                var view = this._searchResults[i];
+                if (view.searchCanceled)
+                    view.searchCanceled();
+                delete view.currentQuery;
+            }
+        }
+
+        WebInspector.updateSearchMatchesCount(0, this);
+
+        if (this._currentSearchChunkIntervalIdentifier) {
+            clearInterval(this._currentSearchChunkIntervalIdentifier);
+            delete this._currentSearchChunkIntervalIdentifier;
+        }
+
+        this._totalSearchMatches = 0;
+        this._currentSearchResultIndex = 0;
+        this._searchResults = [];
+    },
+
+    performSearch: function(query)
+    {
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled(true);
+
+        var searchableViews = this.searchableViews;
+        if (!searchableViews || !searchableViews.length)
+            return;
+
+        var parentElement = this.viewsContainerElement;
+        var visibleView = this.visibleView;
+        var sortFuction = this.searchResultsSortFunction;
+
+        var matchesCountUpdateTimeout = null;
+
+        function updateMatchesCount()
+        {
+            WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this);
+            matchesCountUpdateTimeout = null;
+        }
+
+        function updateMatchesCountSoon()
+        {
+            if (matchesCountUpdateTimeout)
+                return;
+            // Update the matches count every half-second so it doesn't feel twitchy.
+            matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
+        }
+
+        function finishedCallback(view, searchMatches)
+        {
+            if (!searchMatches)
+                return;
+
+            this._totalSearchMatches += searchMatches;
+            this._searchResults.push(view);
+
+            if (sortFuction)
+                this._searchResults.sort(sortFuction);
+
+            if (this.searchMatchFound)
+                this.searchMatchFound(view, searchMatches);
+
+            updateMatchesCountSoon.call(this);
+
+            if (view === visibleView)
+                view.jumpToFirstSearchResult();
+        }
+
+        var i = 0;
+        var panel = this;
+        var boundFinishedCallback = finishedCallback.bind(this);
+        var chunkIntervalIdentifier = null;
+
+        // Split up the work into chunks so we don't block the
+        // UI thread while processing.
+
+        function processChunk()
+        {
+            var view = searchableViews[i];
+
+            if (++i >= searchableViews.length) {
+                if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+                    delete panel._currentSearchChunkIntervalIdentifier;
+                clearInterval(chunkIntervalIdentifier);
+            }
+
+            if (!view)
+                return;
+
+            if (view.element.parentNode !== parentElement && view.element.parentNode && parentElement)
+                view.detach();
+
+            view.currentQuery = query;
+            view.performSearch(query, boundFinishedCallback);
+        }
+
+        processChunk();
+
+        chunkIntervalIdentifier = setInterval(processChunk, 25);
+        this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        if (!this.showView || !this._searchResults || !this._searchResults.length)
+            return;
+
+        var showFirstResult = false;
+
+        this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+        if (this._currentSearchResultIndex === -1) {
+            this._currentSearchResultIndex = 0;
+            showFirstResult = true;
+        }
+
+        var currentView = this._searchResults[this._currentSearchResultIndex];
+
+        if (currentView.showingLastSearchResult()) {
+            if (++this._currentSearchResultIndex >= this._searchResults.length)
+                this._currentSearchResultIndex = 0;
+            currentView = this._searchResults[this._currentSearchResultIndex];
+            showFirstResult = true;
+        }
+
+        if (currentView !== this.visibleView) {
+            this.showView(currentView);
+            WebInspector.focusSearchField();
+        }
+
+        if (showFirstResult)
+            currentView.jumpToFirstSearchResult();
+        else
+            currentView.jumpToNextSearchResult();
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        if (!this.showView || !this._searchResults || !this._searchResults.length)
+            return;
+
+        var showLastResult = false;
+
+        this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+        if (this._currentSearchResultIndex === -1) {
+            this._currentSearchResultIndex = 0;
+            showLastResult = true;
+        }
+
+        var currentView = this._searchResults[this._currentSearchResultIndex];
+
+        if (currentView.showingFirstSearchResult()) {
+            if (--this._currentSearchResultIndex < 0)
+                this._currentSearchResultIndex = (this._searchResults.length - 1);
+            currentView = this._searchResults[this._currentSearchResultIndex];
+            showLastResult = true;
+        }
+
+        if (currentView !== this.visibleView) {
+            this.showView(currentView);
+            WebInspector.focusSearchField();
+        }
+
+        if (showLastResult)
+            currentView.jumpToLastSearchResult();
+        else
+            currentView.jumpToPreviousSearchResult();
+    },
+
+    createSidebar: function(parentElement, resizerParentElement)
+    {
+        if (this.sidebarElement)
+            return;
+
+        if (!parentElement)
+            parentElement = this.element;
+
+        if (!resizerParentElement)
+            resizerParentElement = parentElement;
+
+        this.sidebarElement = document.createElement("div");
+        this.sidebarElement.className = "sidebar";
+        parentElement.appendChild(this.sidebarElement);
+
+        this.sidebarResizeElement = document.createElement("div");
+        this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+        this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+        resizerParentElement.appendChild(this.sidebarResizeElement);
+
+        this.sidebarTreeElement = document.createElement("ol");
+        this.sidebarTreeElement.className = "sidebar-tree";
+        this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+        this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+        this.sidebarTree.panel = this;
+    },
+
+    _sidebarWidthSettingName: function()
+    {
+        return this._panelName + "SidebarWidth";
+    },
+
+    _startSidebarDragging: function(event)
+    {
+        WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+    },
+
+    _sidebarDragging: function(event)
+    {
+        this.updateSidebarWidth(event.pageX);
+
+        event.preventDefault();
+    },
+
+    _endSidebarDragging: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+        this.saveSidebarWidth();
+    },
+
+    updateSidebarWidth: function(width)
+    {
+        if (!this.sidebarElement)
+            return;
+
+        if (this.sidebarElement.offsetWidth <= 0) {
+            // The stylesheet hasn't loaded yet or the window is closed,
+            // so we can't calculate what is need. Return early.
+            return;
+        }
+
+        if (!("_currentSidebarWidth" in this))
+            this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+        if (typeof width === "undefined")
+            width = this._currentSidebarWidth;
+
+        width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+        this._currentSidebarWidth = width;
+        this.setSidebarWidth(width);
+
+        this.updateMainViewWidth(width);
+    },
+
+    setSidebarWidth: function(width)
+    {
+        this.sidebarElement.style.width = width + "px";
+        this.sidebarResizeElement.style.left = (width - 3) + "px";
+    },
+
+    restoreSidebarWidth: function()
+    {
+        var sidebarWidth = WebInspector.settings[this._sidebarWidthSettingName()];
+        this.updateSidebarWidth(sidebarWidth);
+    },
+
+    saveSidebarWidth: function()
+    {
+        if (!this.sidebarElement)
+            return;
+        WebInspector.settings[this._sidebarWidthSettingName()] = this.sidebarElement.offsetWidth;
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        // Should be implemented by ancestors.
+    },
+
+    resize: function()
+    {
+        var visibleView = this.visibleView;
+        if (visibleView && "resize" in visibleView)
+            visibleView.resize();
+    },
+
+    canShowSourceLine: function(url, line)
+    {
+        return false;
+    },
+
+    showSourceLine: function(url, line)
+    {
+        return false;
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [];
+    },
+
+    _storeScrollPositions: function()
+    {
+        var elements = this.elementsToRestoreScrollPositionsFor();
+        for (var i = 0; i < elements.length; ++i) {
+            var container = elements[i];
+            container._scrollTop = container.scrollTop;
+        }
+    },
+
+    _restoreScrollPositions: function()
+    {
+        var elements = this.elementsToRestoreScrollPositionsFor();
+        for (var i = 0; i < elements.length; ++i) {
+            var container = elements[i];
+            if (container._scrollTop)
+                container.scrollTop = container._scrollTop;
+        }
+    }
+}
+
+WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/PanelEnablerView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PanelEnablerView.js
new file mode 100644
index 0000000..5c26604
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PanelEnablerView.js
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("panel-enabler-view");
+    this.element.addStyleClass(identifier);
+
+    this.contentElement = document.createElement("div");
+    this.contentElement.className = "panel-enabler-view-content";
+    this.element.appendChild(this.contentElement);
+
+    this.imageElement = document.createElement("img");
+    this.contentElement.appendChild(this.imageElement);
+
+    this.choicesForm = document.createElement("form");
+    this.contentElement.appendChild(this.choicesForm);
+
+    this.headerElement = document.createElement("h1");
+    this.headerElement.textContent = headingText;
+    this.choicesForm.appendChild(this.headerElement);
+
+    var self = this;
+    function enableOption(text, checked) {
+        var label = document.createElement("label");
+        var option = document.createElement("input");
+        option.type = "radio";
+        option.name = "enable-option";
+        if (checked)
+            option.checked = true;
+        label.appendChild(option);
+        label.appendChild(document.createTextNode(text));
+        self.choicesForm.appendChild(label);
+        return option;
+    };
+
+    this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true);
+    this.enabledAlways = enableOption(WebInspector.UIString("Always enable"));
+
+    this.disclaimerElement = document.createElement("div");
+    this.disclaimerElement.className = "panel-enabler-disclaimer";
+    this.disclaimerElement.textContent = disclaimerText;
+    this.choicesForm.appendChild(this.disclaimerElement);
+
+    this.enableButton = document.createElement("button");
+    this.enableButton.setAttribute("type", "button");
+    this.enableButton.textContent = buttonTitle;
+    this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false);
+    this.choicesForm.appendChild(this.enableButton);
+}
+
+WebInspector.PanelEnablerView.prototype = {
+    _enableButtonCicked: function()
+    {
+        this.dispatchEventToListeners("enable clicked");
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+
+        setTimeout(this.resize.bind(this), 0);
+    },
+
+    resize: function()
+    {
+        this.imageElement.removeStyleClass("hidden");
+
+        if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth))
+            this.imageElement.addStyleClass("hidden");
+    },
+
+    get alwaysEnabled() {
+        return this.enabledAlways.checked;
+    }
+}
+
+WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Placard.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Placard.js
new file mode 100644
index 0000000..9a415c4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Placard.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Placard = function(title, subtitle)
+{
+    this.element = document.createElement("div");
+    this.element.className = "placard";
+    this.element.placard = this;
+
+    this.titleElement = document.createElement("div");
+    this.titleElement.className = "title";
+
+    this.subtitleElement = document.createElement("div");
+    this.subtitleElement.className = "subtitle";
+
+    this.element.appendChild(this.subtitleElement);
+    this.element.appendChild(this.titleElement);
+
+    this.title = title;
+    this.subtitle = subtitle;
+    this.selected = false;
+}
+
+WebInspector.Placard.prototype = {
+    get title()
+    {
+        return this._title;
+    },
+
+    set title(x)
+    {
+        if (this._title === x)
+            return;
+        this._title = x;
+        this.titleElement.textContent = x;
+    },
+
+    get subtitle()
+    {
+        return this._subtitle;
+    },
+
+    set subtitle(x)
+    {
+        if (this._subtitle === x)
+            return;
+        this._subtitle = x;
+        this.subtitleElement.textContent = x;
+    },
+
+    get selected()
+    {
+        return this._selected;
+    },
+
+    set selected(x)
+    {
+        if (x)
+            this.select();
+        else
+            this.deselect();
+    },
+
+    select: function()
+    {
+        if (this._selected)
+            return;
+        this._selected = true;
+        this.element.addStyleClass("selected");
+    },
+
+    deselect: function()
+    {
+        if (!this._selected)
+            return;
+        this._selected = false;
+        this.element.removeStyleClass("selected");
+    },
+
+    toggleSelected: function()
+    {
+        this.selected = !this.selected;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/PleaseWaitMessage.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PleaseWaitMessage.js
new file mode 100644
index 0000000..54d805d
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PleaseWaitMessage.js
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PleaseWaitMessage = function()
+{
+    this.element = document.createElement("div");
+    this.element.className = "please-wait-msg";
+    this.element.textContent = WebInspector.UIString("Please wait\u2026");
+
+    this.cancelButton = document.createElement("button");
+    this.cancelButton.textContent = WebInspector.UIString("Cancel");
+    this.cancelButton.addEventListener("click", this._cancelClicked.bind(this), false);
+}
+
+WebInspector.PleaseWaitMessage.prototype = {
+    _cancelClicked: function()
+    {
+        if (this._cancelCallback) {
+            var cancelCallback = this._cancelCallback;
+            delete this._cancelCallback;
+            cancelCallback();
+        }
+    },
+
+    hide: function()
+    {
+        var instance = WebInspector.PleaseWaitMessage.prototype.instance;
+        var message = instance.element;
+        if (message.parentNode)
+            message.parentNode.removeChild(message);
+    },
+
+    get instance()
+    {
+        if (!"_instance" in WebInspector.PleaseWaitMessage.prototype)
+            WebInspector.PleaseWaitMessage.prototype._instance = new WebInspector.PleaseWaitMessage();
+        return WebInspector.PleaseWaitMessage.prototype._instance;
+    },
+
+    show: function(element, cancelCallback)
+    {
+        var instance = WebInspector.PleaseWaitMessage.prototype.instance;
+        var message = instance.element;
+        if (message.parentNode === element)
+            return;
+        else if (message.parentNode)
+            message.parentNode.removeChild(message);
+        if (message.childNodes.length > 1)
+            message.removeChild(instance.cancelButton);
+        if (cancelCallback) {
+            message.appendChild(instance.cancelButton);
+            instance._cancelCallback = cancelCallback;
+        }
+        element.appendChild(message);
+    },
+
+    startAction: function(element, actionCallback, cancelCallback)
+    {
+        var instance = WebInspector.PleaseWaitMessage.prototype.instance;
+        var message = instance.element;
+        if (message.parentNode === element) {
+            actionCallback();
+            return;
+        }
+     
+        function doAction()
+        {
+            try {
+                actionCallback();
+            } finally {
+                if (message.parentNode)
+                    message.parentNode.removeChild(message);
+            }
+        }
+
+        WebInspector.PleaseWaitMessage.prototype.show(element, cancelCallback);
+        setTimeout(doAction, 0);
+    }
+};
+
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Popover.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Popover.js
new file mode 100644
index 0000000..32535e9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Popover.js
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Popover = function(contentElement)
+{
+    this.element = document.createElement("div");
+    this.element.className = "popover";
+
+    this._popupArrowElement = document.createElement("div");
+    this._popupArrowElement.className = "arrow";
+    this.element.appendChild(this._popupArrowElement);
+
+    this.contentElement = contentElement;
+    this._contentDiv = document.createElement("div");
+    this._contentDiv.className = "content";
+}
+
+WebInspector.Popover.prototype = {
+    show: function(anchor, preferredWidth, preferredHeight)
+    {
+        // This should not happen, but we hide previous popup to be on the safe side.
+        if (WebInspector.Popover._popoverElement)
+            document.body.removeChild(WebInspector.Popover._popoverElement);
+        WebInspector.Popover._popoverElement = this.element;
+
+        // Temporarily attach in order to measure preferred dimensions.
+        this.contentElement.positionAt(0, 0);
+        document.body.appendChild(this.contentElement);
+        var preferredWidth = preferredWidth || this.contentElement.offsetWidth;
+        var preferredHeight = preferredHeight || this.contentElement.offsetHeight;
+
+        this._contentDiv.appendChild(this.contentElement);
+        this.element.appendChild(this._contentDiv);
+        document.body.appendChild(this.element);
+        this._positionElement(anchor, preferredWidth, preferredHeight);
+    },
+
+    hide: function()
+    {
+        if (WebInspector.Popover._popoverElement) {
+            delete WebInspector.Popover._popoverElement;
+            document.body.removeChild(this.element);
+        }
+    },
+
+    _positionElement: function(anchorElement, preferredWidth, preferredHeight)
+    {
+        const borderWidth = 25;
+        const scrollerWidth = 11;
+        const arrowHeight = 15;
+        const arrowOffset = 10;
+        const borderRadius = 10;
+
+        // Skinny tooltips are not pretty, their arrow location is not nice.
+        preferredWidth = Math.max(preferredWidth, 50);
+        const totalWidth = window.innerWidth;
+        const totalHeight = window.innerHeight;
+
+        var anchorBox = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight};
+        while (anchorElement !== document.body) {
+            if (anchorElement.scrollLeft)
+                anchorBox.x -= anchorElement.scrollLeft;
+            if (anchorElement.scrollTop)
+                anchorBox.y -= anchorElement.scrollTop;
+            anchorElement = anchorElement.parentElement;
+        }
+
+        var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight };
+
+        var verticalAlignment;
+        var roomAbove = anchorBox.y;
+        var roomBelow = totalHeight - anchorBox.y - anchorBox.height;
+
+        if (roomAbove > roomBelow) {
+            // Positioning above the anchor.
+            if (anchorBox.y > newElementPosition.height + arrowHeight + borderRadius)
+                newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight;
+            else {
+                newElementPosition.y = borderRadius * 2;
+                newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight;
+            }
+            verticalAlignment = "bottom";
+        } else {
+            // Positioning below the anchor.
+            newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight;
+            if (newElementPosition.y + newElementPosition.height + arrowHeight - borderWidth >= totalHeight)
+                newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height - borderRadius * 2 - arrowHeight;
+            // Align arrow.
+            verticalAlignment = "top";
+        }
+
+        var horizontalAlignment;
+        if (anchorBox.x + newElementPosition.width < totalWidth) {
+            newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset);
+            horizontalAlignment = "left";
+        } else if (newElementPosition.width + borderRadius * 2 < totalWidth) {
+            newElementPosition.x = totalWidth - newElementPosition.width - borderRadius;
+            horizontalAlignment = "right";
+            // Position arrow accurately.
+            var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox.width - borderRadius - arrowOffset);
+            arrowRightPosition += anchorBox.width / 2;
+            this._popupArrowElement.style.right = arrowRightPosition + "px";
+        } else {
+            newElementPosition.x = borderRadius;
+            newElementPosition.width = totalWidth - borderRadius * 2;
+            newElementPosition.height += scrollerWidth;
+            horizontalAlignment = "left";
+            if (verticalAlignment === "bottom")
+                newElementPosition.y -= scrollerWidth;
+            // Position arrow accurately.
+            this._popupArrowElement.style.left = Math.max(0, anchorBox.x - borderRadius * 2 - arrowOffset) + "px";
+            this._popupArrowElement.style.left += anchorBox.width / 2;
+        }
+
+        this.element.className = "popover " + verticalAlignment + "-" + horizontalAlignment + "-arrow";
+        this.element.positionAt(newElementPosition.x - borderWidth, newElementPosition.y - borderWidth);
+        this.element.style.width = newElementPosition.width + borderWidth * 2 + "px";
+        this.element.style.height = newElementPosition.height + borderWidth * 2 + "px";
+    }
+}
+
+WebInspector.PopoverHelper = function(panelElement, getAnchor, showPopup, showOnClick, onHide)
+{
+    this._panelElement = panelElement;
+    this._getAnchor = getAnchor;
+    this._showPopup = showPopup;
+    this._showOnClick = showOnClick;
+    this._onHide = onHide;
+    panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false);
+    panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false);
+    this.setTimeout(1000);
+}
+
+WebInspector.PopoverHelper.prototype = {
+    setTimeout: function(timeout)
+    {
+         this._timeout = timeout;
+    },
+
+    _mouseDown: function(event)
+    {
+        this._killHidePopupTimer();
+        this._handleMouseAction(event, true);
+    },
+
+    _mouseMove: function(event)
+    {
+        // Pretend that nothing has happened.
+        if (this._hoverElement === event.target || (this._hoverElement && this._hoverElement.isAncestor(event.target)))
+            return;
+
+        // User has 500ms (this._timeout / 2) to reach the popup.
+        if (this._popup && !this._hidePopupTimer) {
+            var self = this;
+            function doHide()
+            {
+                self._hidePopup();
+                delete self._hidePopupTimer;
+            }
+            this._hidePopupTimer = setTimeout(doHide, this._timeout / 2);
+        }
+
+        this._handleMouseAction(event);
+    },
+
+    _handleMouseAction: function(event, isMouseDown)
+    {
+        this._resetHoverTimer();
+
+        this._hoverElement = this._getAnchor(event.target);
+        if (!this._hoverElement)
+            return;
+
+        const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout);
+        this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay);
+    },
+
+    _resetHoverTimer: function()
+    {
+        if (this._hoverTimer) {
+            clearTimeout(this._hoverTimer);
+            delete this._hoverTimer;
+        }
+    },
+
+    hidePopup: function()
+    {
+        this._resetHoverTimer();
+        this._hidePopup();
+    },
+
+    _hidePopup: function()
+    {
+        if (!this._popup)
+            return;
+
+        if (this._onHide)
+            this._onHide();
+
+        this._popup.hide();
+        delete this._popup;
+    },
+
+    _mouseHover: function(element)
+    {
+        delete this._hoverTimer;
+
+        this._popup = this._showPopup(element);
+        if (this._popup)
+            this._popup.contentElement.addEventListener("mousemove", this._killHidePopupTimer.bind(this), true);
+    },
+
+    _killHidePopupTimer: function()
+    {
+        if (this._hidePopupTimer) {
+            clearTimeout(this._hidePopupTimer);
+            delete this._hidePopupTimer;
+
+            // We know that we reached the popup, but we might have moved over other elements.
+            // Discard pending command.
+            this._resetHoverTimer();
+        }
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileDataGridTree.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileDataGridTree.js
new file mode 100644
index 0000000..7988674
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileDataGridTree.js
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProfileDataGridNode = function(profileView, profileNode, owningTree, hasChildren)
+{
+    this.profileView = profileView;
+    this.profileNode = profileNode;
+
+    WebInspector.DataGridNode.call(this, null, hasChildren);
+
+    this.addEventListener("populate", this._populate, this);
+
+    this.tree = owningTree;
+
+    this.childrenByCallUID = {};
+    this.lastComparator = null;
+
+    this.callUID = profileNode.callUID;
+    this.selfTime = profileNode.selfTime;
+    this.totalTime = profileNode.totalTime;
+    this.functionName = profileNode.functionName;
+    this.numberOfCalls = profileNode.numberOfCalls;
+    this.url = profileNode.url;
+}
+
+WebInspector.ProfileDataGridNode.prototype = {
+    get data()
+    {
+        function formatMilliseconds(time)
+        {
+            return Number.secondsToString(time / 1000, !Preferences.samplingCPUProfiler);
+        }
+
+        var data = {};
+
+        data["function"] = this.functionName;
+        data["calls"] = this.numberOfCalls;
+
+        if (this.profileView.showSelfTimeAsPercent)
+            data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent);
+        else
+            data["self"] = formatMilliseconds(this.selfTime);
+
+        if (this.profileView.showTotalTimeAsPercent)
+            data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent);
+        else
+            data["total"] = formatMilliseconds(this.totalTime);
+
+        if (this.profileView.showAverageTimeAsPercent)
+            data["average"] = WebInspector.UIString("%.2f%%", this.averagePercent);
+        else
+            data["average"] = formatMilliseconds(this.averageTime);
+
+        return data;
+    },
+
+    createCell: function(columnIdentifier)
+    {
+        var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+
+        if (columnIdentifier === "self" && this._searchMatchedSelfColumn)
+            cell.addStyleClass("highlight");
+        else if (columnIdentifier === "total" && this._searchMatchedTotalColumn)
+            cell.addStyleClass("highlight");
+        else if (columnIdentifier === "average" && this._searchMatchedAverageColumn)
+            cell.addStyleClass("highlight");
+        else if (columnIdentifier === "calls" && this._searchMatchedCallsColumn)
+            cell.addStyleClass("highlight");
+
+        if (columnIdentifier !== "function")
+            return cell;
+
+        if (this.profileNode._searchMatchedFunctionColumn)
+            cell.addStyleClass("highlight");
+
+        if (this.profileNode.url) {
+            var lineNumber;
+            if (this.profileNode.lineNumber > 0)
+                lineNumber = this.profileNode.lineNumber;
+            var urlElement = WebInspector.linkifyResourceAsNode(this.profileNode.url, "scripts", lineNumber, "profile-node-file");
+            cell.insertBefore(urlElement, cell.firstChild);
+        }
+
+        return cell;
+    },
+
+    select: function(supressSelectedEvent)
+    {
+        WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
+        this.profileView._dataGridNodeSelected(this);
+    },
+
+    deselect: function(supressDeselectedEvent)
+    {
+        WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
+        this.profileView._dataGridNodeDeselected(this);
+    },
+
+    sort: function(/*Function*/ comparator, /*Boolean*/ force)
+    {
+        var gridNodeGroups = [[this]];
+
+        for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) {
+            var gridNodes = gridNodeGroups[gridNodeGroupIndex];
+            var count = gridNodes.length;
+
+            for (var index = 0; index < count; ++index) {
+                var gridNode = gridNodes[index];
+
+                // If the grid node is collapsed, then don't sort children (save operation for later).
+                // If the grid node has the same sorting as previously, then there is no point in sorting it again.
+                if (!force && (!gridNode.expanded || gridNode.lastComparator === comparator)) {
+                    if (gridNode.children.length)
+                        gridNode.shouldRefreshChildren = true;
+                    continue;
+                }
+
+                gridNode.lastComparator = comparator;
+
+                var children = gridNode.children;
+                var childCount = children.length;
+
+                if (childCount) {
+                    children.sort(comparator);
+
+                    for (var childIndex = 0; childIndex < childCount; ++childIndex)
+                        children[childIndex]._recalculateSiblings(childIndex);
+
+                    gridNodeGroups.push(children);
+                }
+            }
+        }
+    },
+
+    insertChild: function(/*ProfileDataGridNode*/ profileDataGridNode, index)
+    {
+        WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index);
+
+        this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode;
+    },
+
+    removeChild: function(/*ProfileDataGridNode*/ profileDataGridNode)
+    {
+        WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode);
+
+        delete this.childrenByCallUID[profileDataGridNode.callUID];
+    },
+
+    removeChildren: function(/*ProfileDataGridNode*/ profileDataGridNode)
+    {
+        WebInspector.DataGridNode.prototype.removeChildren.call(this);
+
+        this.childrenByCallUID = {};
+    },
+
+    findChild: function(/*Node*/ node)
+    {
+        if (!node)
+            return null;
+        return this.childrenByCallUID[node.callUID];
+    },
+
+    get averageTime()
+    {
+        return this.selfTime / Math.max(1, this.numberOfCalls);
+    },
+
+    get averagePercent()
+    {
+        return this.averageTime / this.tree.totalTime * 100.0;
+    },
+
+    get selfPercent()
+    {
+        return this.selfTime / this.tree.totalTime * 100.0;
+    },
+
+    get totalPercent()
+    {
+        return this.totalTime / this.tree.totalTime * 100.0;
+    },
+
+    get _parent()
+    {
+        return this.parent !== this.dataGrid ? this.parent : this.tree;
+    },
+
+    _populate: function(event)
+    {
+        this._sharedPopulate();
+
+        if (this._parent) {
+            var currentComparator = this._parent.lastComparator;
+
+            if (currentComparator)
+                this.sort(currentComparator, true);
+        }
+
+        if (this.removeEventListener)
+            this.removeEventListener("populate", this._populate, this);
+    },
+
+    // When focusing and collapsing we modify lots of nodes in the tree.
+    // This allows us to restore them all to their original state when we revert.
+    _save: function()
+    {
+        if (this._savedChildren)
+            return;
+
+        this._savedSelfTime = this.selfTime;
+        this._savedTotalTime = this.totalTime;
+        this._savedNumberOfCalls = this.numberOfCalls;
+
+        this._savedChildren = this.children.slice();
+    },
+
+    // When focusing and collapsing we modify lots of nodes in the tree.
+    // This allows us to restore them all to their original state when we revert.
+    _restore: function()
+    {
+        if (!this._savedChildren)
+            return;
+
+        this.selfTime = this._savedSelfTime;
+        this.totalTime = this._savedTotalTime;
+        this.numberOfCalls = this._savedNumberOfCalls;
+
+        this.removeChildren();
+
+        var children = this._savedChildren;
+        var count = children.length;
+
+        for (var index = 0; index < count; ++index) {
+            children[index]._restore();
+            this.appendChild(children[index]);
+        }
+    },
+
+    _merge: function(child, shouldAbsorb)
+    {
+        this.selfTime += child.selfTime;
+
+        if (!shouldAbsorb) {
+            this.totalTime += child.totalTime;
+            this.numberOfCalls += child.numberOfCalls;
+        }
+
+        var children = this.children.slice();
+
+        this.removeChildren();
+
+        var count = children.length;
+
+        for (var index = 0; index < count; ++index) {
+            if (!shouldAbsorb || children[index] !== child)
+                this.appendChild(children[index]);
+        }
+
+        children = child.children.slice();
+        count = children.length;
+
+        for (var index = 0; index < count; ++index) {
+            var orphanedChild = children[index],
+                existingChild = this.childrenByCallUID[orphanedChild.callUID];
+
+            if (existingChild)
+                existingChild._merge(orphanedChild, false);
+            else
+                this.appendChild(orphanedChild);
+        }
+    }
+}
+
+WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.ProfileDataGridTree = function(profileView, profileNode)
+{
+    this.tree = this;
+    this.children = [];
+
+    this.profileView = profileView;
+
+    this.totalTime = profileNode.totalTime;
+    this.lastComparator = null;
+
+    this.childrenByCallUID = {};
+}
+
+WebInspector.ProfileDataGridTree.prototype = {
+    get expanded()
+    {
+        return true;
+    },
+
+    appendChild: function(child)
+    {
+        this.insertChild(child, this.children.length);
+    },
+
+    insertChild: function(child, index)
+    {
+        this.children.splice(index, 0, child);
+        this.childrenByCallUID[child.callUID] = child;
+    },
+
+    removeChildren: function()
+    {
+        this.children = [];
+        this.childrenByCallUID = {};
+    },
+
+    findChild: WebInspector.ProfileDataGridNode.prototype.findChild,
+    sort: WebInspector.ProfileDataGridNode.prototype.sort,
+
+    _save: function()
+    {
+        if (this._savedChildren)
+            return;
+
+        this._savedTotalTime = this.totalTime;
+        this._savedChildren = this.children.slice();
+    },
+
+    restore: function()
+    {
+        if (!this._savedChildren)
+            return;
+
+        this.children = this._savedChildren;
+        this.totalTime = this._savedTotalTime;
+
+        var children = this.children;
+        var count = children.length;
+
+        for (var index = 0; index < count; ++index)
+            children[index]._restore();
+
+        this._savedChildren = null;
+    }
+}
+
+WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}];
+
+WebInspector.ProfileDataGridTree.propertyComparator = function(/*String*/ property, /*Boolean*/ isAscending)
+{
+    var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property];
+
+    if (!comparator) {
+        if (isAscending) {
+            comparator = function(lhs, rhs)
+            {
+                if (lhs[property] < rhs[property])
+                    return -1;
+
+                if (lhs[property] > rhs[property])
+                    return 1;
+
+                return 0;
+            }
+        } else {
+            comparator = function(lhs, rhs)
+            {
+                if (lhs[property] > rhs[property])
+                    return -1;
+
+                if (lhs[property] < rhs[property])
+                    return 1;
+
+                return 0;
+            }
+        }
+
+        this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
+    }
+
+    return comparator;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileView.js
new file mode 100644
index 0000000..c325bf7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfileView.js
@@ -0,0 +1,622 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// FIXME: Rename the file.
+
+WebInspector.CPUProfileView = function(profile)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("profile-view");
+
+    this.showSelfTimeAsPercent = true;
+    this.showTotalTimeAsPercent = true;
+    this.showAverageTimeAsPercent = true;
+
+    var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true },
+                    "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true },
+                    "average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true },
+                    "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
+                    "function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } };
+
+    if (Preferences.samplingCPUProfiler) {
+        delete columns.average;
+        delete columns.calls;
+    }
+
+    this.dataGrid = new WebInspector.DataGrid(columns);
+    this.dataGrid.addEventListener("sorting changed", this._sortData, this);
+    this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
+    this.element.appendChild(this.dataGrid.element);
+
+    this.viewSelectElement = document.createElement("select");
+    this.viewSelectElement.className = "status-bar-item";
+    this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
+    this.view = "Heavy";
+
+    var heavyViewOption = document.createElement("option");
+    heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)");
+    var treeViewOption = document.createElement("option");
+    treeViewOption.label = WebInspector.UIString("Tree (Top Down)");
+    this.viewSelectElement.appendChild(heavyViewOption);
+    this.viewSelectElement.appendChild(treeViewOption);
+
+    this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item");
+    this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+
+    this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item");
+    this.focusButton.disabled = true;
+    this.focusButton.addEventListener("click", this._focusClicked.bind(this), false);
+
+    this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item");
+    this.excludeButton.disabled = true;
+    this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false);
+
+    this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item");
+    this.resetButton.visible = false;
+    this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);
+
+    this.profile = profile;
+
+    var self = this;
+    function profileCallback(profile)
+    {
+        self.profile.head = profile.head;
+        self._assignParentsInProfile();
+      
+        self.profileDataGridTree = self.bottomUpProfileDataGridTree;
+        self.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator("selfTime", false));
+     
+        self.refresh();
+     
+        self._updatePercentButton();
+    }
+
+    InspectorBackend.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
+}
+
+WebInspector.CPUProfileView.prototype = {
+    get statusBarItems()
+    {
+        return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element];
+    },
+
+    get profile()
+    {
+        return this._profile;
+    },
+
+    set profile(profile)
+    {
+        this._profile = profile;
+    },
+
+    get bottomUpProfileDataGridTree()
+    {
+        if (!this._bottomUpProfileDataGridTree)
+            this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head);
+        return this._bottomUpProfileDataGridTree;
+    },
+
+    get topDownProfileDataGridTree()
+    {
+        if (!this._topDownProfileDataGridTree)
+            this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head);
+        return this._topDownProfileDataGridTree;
+    },
+
+    get currentTree()
+    {
+        return this._currentTree;
+    },
+
+    set currentTree(tree)
+    {
+        this._currentTree = tree;
+        this.refresh();
+    },
+
+    get topDownTree()
+    {
+        if (!this._topDownTree) {
+            this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head);
+            this._sortProfile(this._topDownTree);
+        }
+
+        return this._topDownTree;
+    },
+
+    get bottomUpTree()
+    {
+        if (!this._bottomUpTree) {
+            this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head);
+            this._sortProfile(this._bottomUpTree);
+        }
+
+        return this._bottomUpTree;
+    },
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this.dataGrid.updateWidths();
+    },
+
+    hide: function()
+    {
+        WebInspector.View.prototype.hide.call(this);
+        this._currentSearchResultIndex = -1;
+    },
+
+    resize: function()
+    {
+        if (this.dataGrid)
+            this.dataGrid.updateWidths();
+    },
+
+    refresh: function()
+    {
+        var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;
+
+        this.dataGrid.removeChildren();
+
+        var children = this.profileDataGridTree.children;
+        var count = children.length;
+
+        for (var index = 0; index < count; ++index)
+            this.dataGrid.appendChild(children[index]);
+
+        if (selectedProfileNode)
+            selectedProfileNode.selected = true;
+    },
+
+    refreshVisibleData: function()
+    {
+        var child = this.dataGrid.children[0];
+        while (child) {
+            child.refresh();
+            child = child.traverseNextNode(false, null, true);
+        }
+    },
+
+    refreshShowAsPercents: function()
+    {
+        this._updatePercentButton();
+        this.refreshVisibleData();
+    },
+
+    searchCanceled: function()
+    {
+        if (this._searchResults) {
+            for (var i = 0; i < this._searchResults.length; ++i) {
+                var profileNode = this._searchResults[i].profileNode;
+
+                delete profileNode._searchMatchedSelfColumn;
+                delete profileNode._searchMatchedTotalColumn;
+                delete profileNode._searchMatchedCallsColumn;
+                delete profileNode._searchMatchedFunctionColumn;
+
+                profileNode.refresh();
+            }
+        }
+
+        delete this._searchFinishedCallback;
+        this._currentSearchResultIndex = -1;
+        this._searchResults = [];
+    },
+
+    performSearch: function(query, finishedCallback)
+    {
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled();
+
+        query = query.trim();
+
+        if (!query.length)
+            return;
+
+        this._searchFinishedCallback = finishedCallback;
+
+        var greaterThan = (query.indexOf(">") === 0);
+        var lessThan = (query.indexOf("<") === 0);
+        var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1));
+        var percentUnits = (query.lastIndexOf("%") === (query.length - 1));
+        var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2));
+        var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1));
+
+        var queryNumber = parseFloat(query);
+        if (greaterThan || lessThan || equalTo) {
+            if (equalTo && (greaterThan || lessThan))
+                queryNumber = parseFloat(query.substring(2));
+            else
+                queryNumber = parseFloat(query.substring(1));
+        }
+
+        var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber);
+
+        // Make equalTo implicitly true if it wasn't specified there is no other operator.
+        if (!isNaN(queryNumber) && !(greaterThan || lessThan))
+            equalTo = true;
+
+        function matchesQuery(/*ProfileDataGridNode*/ profileDataGridNode)
+        {
+            delete profileDataGridNode._searchMatchedSelfColumn;
+            delete profileDataGridNode._searchMatchedTotalColumn;
+            delete profileDataGridNode._searchMatchedAverageColumn;
+            delete profileDataGridNode._searchMatchedCallsColumn;
+            delete profileDataGridNode._searchMatchedFunctionColumn;
+
+            if (percentUnits) {
+                if (lessThan) {
+                    if (profileDataGridNode.selfPercent < queryNumber)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalPercent < queryNumber)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                } else if (greaterThan) {
+                    if (profileDataGridNode.selfPercent > queryNumber)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalPercent > queryNumber)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                }
+
+                if (equalTo) {
+                    if (profileDataGridNode.selfPercent == queryNumber)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalPercent == queryNumber)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                }
+            } else if (millisecondsUnits || secondsUnits) {
+                if (lessThan) {
+                    if (profileDataGridNode.selfTime < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalTime < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averageTime < queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                } else if (greaterThan) {
+                    if (profileDataGridNode.selfTime > queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalTime > queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averageTime > queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                }
+
+                if (equalTo) {
+                    if (profileDataGridNode.selfTime == queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedSelfColumn = true;
+                    if (profileDataGridNode.totalTime == queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedTotalColumn = true;
+                    if (profileDataGridNode.averageTime == queryNumberMilliseconds)
+                        profileDataGridNode._searchMatchedAverageColumn = true;
+                }
+            } else {
+                if (equalTo && profileDataGridNode.numberOfCalls == queryNumber)
+                    profileDataGridNode._searchMatchedCallsColumn = true;
+                if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber)
+                    profileDataGridNode._searchMatchedCallsColumn = true;
+                if (lessThan && profileDataGridNode.numberOfCalls < queryNumber)
+                    profileDataGridNode._searchMatchedCallsColumn = true;
+            }
+
+            if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true))
+                profileDataGridNode._searchMatchedFunctionColumn = true;
+
+            if (profileDataGridNode._searchMatchedSelfColumn ||
+                profileDataGridNode._searchMatchedTotalColumn ||
+                profileDataGridNode._searchMatchedAverageColumn ||
+                profileDataGridNode._searchMatchedCallsColumn ||
+                profileDataGridNode._searchMatchedFunctionColumn)
+            {
+                profileDataGridNode.refresh();
+                return true;
+            }
+
+            return false;
+        }
+
+        var current = this.profileDataGridTree.children[0];
+
+        while (current) {
+            if (matchesQuery(current)) {
+                this._searchResults.push({ profileNode: current });
+            }
+
+            current = current.traverseNextNode(false, null, false);
+        }
+
+        finishedCallback(this, this._searchResults.length);
+    },
+
+    jumpToFirstSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+        this._currentSearchResultIndex = 0;
+        this._jumpToSearchResult(this._currentSearchResultIndex);
+    },
+
+    jumpToLastSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+        this._currentSearchResultIndex = (this._searchResults.length - 1);
+        this._jumpToSearchResult(this._currentSearchResultIndex);
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+        if (++this._currentSearchResultIndex >= this._searchResults.length)
+            this._currentSearchResultIndex = 0;
+        this._jumpToSearchResult(this._currentSearchResultIndex);
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        if (!this._searchResults || !this._searchResults.length)
+            return;
+        if (--this._currentSearchResultIndex < 0)
+            this._currentSearchResultIndex = (this._searchResults.length - 1);
+        this._jumpToSearchResult(this._currentSearchResultIndex);
+    },
+
+    showingFirstSearchResult: function()
+    {
+        return (this._currentSearchResultIndex === 0);
+    },
+
+    showingLastSearchResult: function()
+    {
+        return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+    },
+
+    _jumpToSearchResult: function(index)
+    {
+        var searchResult = this._searchResults[index];
+        if (!searchResult)
+            return;
+
+        var profileNode = searchResult.profileNode;
+        profileNode.reveal();
+        profileNode.select();
+    },
+
+    _changeView: function(event)
+    {
+        if (!event || !this.profile)
+            return;
+
+        if (event.target.selectedIndex == 1 && this.view == "Heavy") {
+            this.profileDataGridTree = this.topDownProfileDataGridTree;
+            this._sortProfile();
+            this.view = "Tree";
+        } else if (event.target.selectedIndex == 0 && this.view == "Tree") {
+            this.profileDataGridTree = this.bottomUpProfileDataGridTree;
+            this._sortProfile();
+            this.view = "Heavy";
+        }
+
+        if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+            return;
+
+        // The current search needs to be performed again. First negate out previous match
+        // count by calling the search finished callback with a negative number of matches.
+        // Then perform the search again the with same query and callback.
+        this._searchFinishedCallback(this, -this._searchResults.length);
+        this.performSearch(this.currentQuery, this._searchFinishedCallback);
+    },
+
+    _percentClicked: function(event)
+    {
+        var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent;
+        this.showSelfTimeAsPercent = !currentState;
+        this.showTotalTimeAsPercent = !currentState;
+        this.showAverageTimeAsPercent = !currentState;
+        this.refreshShowAsPercents();
+    },
+
+    _updatePercentButton: function()
+    {
+        if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
+            this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
+            this.percentButton.toggled = true;
+        } else {
+            this.percentButton.title = WebInspector.UIString("Show total and self times as percentages.");
+            this.percentButton.toggled = false;
+        }
+    },
+
+    _focusClicked: function(event)
+    {
+        if (!this.dataGrid.selectedNode)
+            return;
+
+        this.resetButton.visible = true;
+        this.profileDataGridTree.focus(this.dataGrid.selectedNode);
+        this.refresh();
+        this.refreshVisibleData();
+    },
+
+    _excludeClicked: function(event)
+    {
+        var selectedNode = this.dataGrid.selectedNode
+
+        if (!selectedNode)
+            return;
+
+        selectedNode.deselect();
+
+        this.resetButton.visible = true;
+        this.profileDataGridTree.exclude(selectedNode);
+        this.refresh();
+        this.refreshVisibleData();
+    },
+
+    _resetClicked: function(event)
+    {
+        this.resetButton.visible = false;
+        this.profileDataGridTree.restore();
+        this.refresh();
+        this.refreshVisibleData();
+    },
+
+    _dataGridNodeSelected: function(node)
+    {
+        this.focusButton.disabled = false;
+        this.excludeButton.disabled = false;
+    },
+
+    _dataGridNodeDeselected: function(node)
+    {
+        this.focusButton.disabled = true;
+        this.excludeButton.disabled = true;
+    },
+
+    _sortData: function(event)
+    {
+        this._sortProfile(this.profile);
+    },
+
+    _sortProfile: function()
+    {
+        var sortAscending = this.dataGrid.sortOrder === "ascending";
+        var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+        var sortProperty = {
+                "average": "averageTime",
+                "self": "selfTime",
+                "total": "totalTime",
+                "calls": "numberOfCalls",
+                "function": "functionName"
+            }[sortColumnIdentifier];
+
+        this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending));
+
+        this.refresh();
+    },
+
+    _mouseDownInDataGrid: function(event)
+    {
+        if (event.detail < 2)
+            return;
+
+        var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+        if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column")))
+            return;
+
+        if (cell.hasStyleClass("total-column"))
+            this.showTotalTimeAsPercent = !this.showTotalTimeAsPercent;
+        else if (cell.hasStyleClass("self-column"))
+            this.showSelfTimeAsPercent = !this.showSelfTimeAsPercent;
+        else if (cell.hasStyleClass("average-column"))
+            this.showAverageTimeAsPercent = !this.showAverageTimeAsPercent;
+
+        this.refreshShowAsPercents();
+
+        event.preventDefault();
+        event.stopPropagation();
+    },
+
+    _assignParentsInProfile: function()
+    {
+        var head = this.profile.head;
+        head.parent = null;
+        head.head = null;
+        var nodesToTraverse = [ { parent: head, children: head.children } ];
+        while (nodesToTraverse.length > 0) {
+            var pair = nodesToTraverse.shift();
+            var parent = pair.parent;
+            var children = pair.children;
+            var length = children.length;
+            for (var i = 0; i < length; ++i) {
+                children[i].head = head;
+                children[i].parent = parent;
+                if (children[i].children.length > 0)
+                    nodesToTraverse.push({ parent: children[i], children: children[i].children });
+            }
+        }
+    }
+}
+
+WebInspector.CPUProfileView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.CPUProfileType = function()
+{
+    WebInspector.ProfileType.call(this, WebInspector.CPUProfileType.TypeId, WebInspector.UIString("CPU PROFILES"));
+    this._recording = false;
+}
+
+WebInspector.CPUProfileType.TypeId = "CPU";
+
+WebInspector.CPUProfileType.prototype = {
+    get buttonTooltip()
+    {
+        return this._recording ? WebInspector.UIString("Stop profiling.") : WebInspector.UIString("Start profiling.");
+    },
+
+    get buttonStyle()
+    {
+        return this._recording ? "record-profile-status-bar-item status-bar-item toggled-on" : "record-profile-status-bar-item status-bar-item";
+    },
+
+    buttonClicked: function()
+    {
+        this._recording = !this._recording;
+
+        if (this._recording)
+            InspectorBackend.startProfiling();
+        else
+            InspectorBackend.stopProfiling();
+    },
+
+    get welcomeMessage()
+    {
+        return WebInspector.UIString("Control CPU profiling by pressing the %s button on the status bar.");
+    },
+
+    setRecordingProfile: function(isProfiling)
+    {
+        this._recording = isProfiling;
+    },
+
+    createSidebarTreeElementForProfile: function(profile)
+    {
+        return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Profile %d"), "profile-sidebar-tree-item");
+    },
+
+    createView: function(profile)
+    {
+        return new WebInspector.CPUProfileView(profile);
+    }
+}
+
+WebInspector.CPUProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfilesPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfilesPanel.js
new file mode 100644
index 0000000..b87ea7f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ProfilesPanel.js
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
+
+WebInspector.ProfileType = function(id, name)
+{
+    this._id = id;
+    this._name = name;
+}
+
+WebInspector.ProfileType.URLRegExp = /webkit-profile:\/\/(.+)\/(.+)#([0-9]+)/;
+
+WebInspector.ProfileType.prototype = {
+    get buttonTooltip()
+    {
+        return "";
+    },
+
+    get buttonStyle()
+    {
+        return undefined;
+    },
+
+    get buttonCaption()
+    {
+        return this.name;
+    },
+
+    get id()
+    {
+        return this._id;
+    },
+
+    get name()
+    {
+        return this._name;
+    },
+
+    buttonClicked: function()
+    {
+    },
+
+    viewForProfile: function(profile)
+    {
+        if (!profile._profileView)
+            profile._profileView = this.createView(profile);
+        return profile._profileView;
+    },
+
+    get welcomeMessage()
+    {
+        return "";
+    },
+
+    // Must be implemented by subclasses.
+    createView: function(profile)
+    {
+        throw new Error("Needs implemented.");
+    },
+
+    // Must be implemented by subclasses.
+    createSidebarTreeElementForProfile: function(profile)
+    {
+        throw new Error("Needs implemented.");
+    }
+}
+
+WebInspector.ProfilesPanel = function()
+{
+    WebInspector.Panel.call(this, "profiles");
+
+    this.createSidebar();
+
+    this._profileTypesByIdMap = {};
+    this._profileTypeButtonsByIdMap = {};
+
+    var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel.");
+    var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower.");
+    var panelEnablerButton = WebInspector.UIString("Enable Profiling");
+    this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+    this.panelEnablerView.addEventListener("enable clicked", this._enableProfiling, this);
+
+    this.element.appendChild(this.panelEnablerView.element);
+
+    this.profileViews = document.createElement("div");
+    this.profileViews.id = "profile-views";
+    this.element.appendChild(this.profileViews);
+
+    this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
+    this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
+
+    this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear all profiles."), "clear-status-bar-item");
+    this.clearResultsButton.addEventListener("click", this._clearProfiles.bind(this), false);
+
+    this.profileViewStatusBarItemsContainer = document.createElement("div");
+    this.profileViewStatusBarItemsContainer.className = "status-bar-items";
+
+    this.welcomeView = new WebInspector.WelcomeView("profiles", WebInspector.UIString("Welcome to the Profiles panel"));
+    this.element.appendChild(this.welcomeView.element);
+
+    this._profiles = [];
+    this._profilerEnabled = Preferences.profilerAlwaysEnabled;
+    this._reset();
+    InspectorBackend.registerDomainDispatcher("Profiler", new WebInspector.ProfilerDispatcher(this));
+}
+
+WebInspector.ProfilesPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Profiles");
+    },
+
+    get statusBarItems()
+    {
+        function clickHandler(profileType, buttonElement)
+        {
+            profileType.buttonClicked.call(profileType);
+            this.updateProfileTypeButtons();
+        }
+
+        var items = [this.enableToggleButton.element];
+        // FIXME: Generate a single "combo-button".
+        for (var typeId in this._profileTypesByIdMap) {
+            var profileType = this.getProfileType(typeId);
+            if (profileType.buttonStyle) {
+                var button = new WebInspector.StatusBarButton(profileType.buttonTooltip, profileType.buttonStyle, profileType.buttonCaption);
+                this._profileTypeButtonsByIdMap[typeId] = button.element;
+                button.element.addEventListener("click", clickHandler.bind(this, profileType, button.element), false);
+                items.push(button.element);
+            }
+        }
+        items.push(this.clearResultsButton.element, this.profileViewStatusBarItemsContainer);
+        return items;
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this._populateProfiles();
+    },
+
+    _profilerWasEnabled: function()
+    {
+        if (this._profilerEnabled)
+            return;
+
+        this._profilerEnabled = true;
+
+        this._reset();
+        if (this.visible)
+            this._populateProfiles();
+    },
+
+    _profilerWasDisabled: function()
+    {
+        if (!this._profilerEnabled)
+            return;
+
+        this._profilerEnabled = false;
+        this._reset();
+    },
+
+    _reset: function()
+    {
+        for (var i = 0; i < this._profiles.length; ++i)
+            delete this._profiles[i]._profileView;
+        delete this.visibleView;
+
+        delete this.currentQuery;
+        this.searchCanceled();
+
+        this._profiles = [];
+        this._profilesIdMap = {};
+        this._profileGroups = {};
+        this._profileGroupsForLinks = {};
+        this._profilesWereRequested = false;
+
+        this.sidebarTreeElement.removeStyleClass("some-expandable");
+
+        for (var typeId in this._profileTypesByIdMap)
+            this.getProfileType(typeId).treeElement.removeChildren();
+
+        this.profileViews.removeChildren();
+
+        this.profileViewStatusBarItemsContainer.removeChildren();
+
+        this.removeAllListeners();
+
+        this._updateInterface();
+        this.welcomeView.show();
+    },
+
+    _clearProfiles: function()
+    {
+        InspectorBackend.clearProfiles();
+        this._reset();
+    },
+
+    registerProfileType: function(profileType)
+    {
+        this._profileTypesByIdMap[profileType.id] = profileType;
+        profileType.treeElement = new WebInspector.SidebarSectionTreeElement(profileType.name, null, true);
+        this.sidebarTree.appendChild(profileType.treeElement);
+        profileType.treeElement.expand();
+        this._addWelcomeMessage(profileType);
+    },
+
+    _addWelcomeMessage: function(profileType)
+    {
+        var message = profileType.welcomeMessage;
+        // Message text is supposed to have a '%s' substring as a placeholder
+        // for a status bar button. If it is there, we split the message in two
+        // parts, and insert the button between them.
+        var buttonPos = message.indexOf("%s");
+        if (buttonPos > -1) {
+            var container = document.createDocumentFragment();
+            var part1 = document.createElement("span");
+            part1.innerHTML = message.substr(0, buttonPos);
+            container.appendChild(part1);
+     
+            var button = new WebInspector.StatusBarButton(profileType.buttonTooltip, profileType.buttonStyle, profileType.buttonCaption);
+            container.appendChild(button.element);
+       
+            var part2 = document.createElement("span");
+            part2.innerHTML = message.substr(buttonPos + 2);
+            container.appendChild(part2);
+            this.welcomeView.addMessage(container);
+        } else
+            this.welcomeView.addMessage(message);
+    },
+
+    _makeKey: function(text, profileTypeId)
+    {
+        return escape(text) + '/' + escape(profileTypeId);
+    },
+
+    _addProfileHeader: function(profile)
+    {
+        if (this.hasTemporaryProfile(profile.typeId)) {
+            if (profile.typeId === WebInspector.CPUProfileType.TypeId)
+                this._removeProfileHeader(this._temporaryRecordingProfile);
+            else
+                this._removeProfileHeader(this._temporaryTakingSnapshot);
+        }
+
+        var typeId = profile.typeId;
+        var profileType = this.getProfileType(typeId);
+        var sidebarParent = profileType.treeElement;
+        var small = false;
+        var alternateTitle;
+
+        profile.__profilesPanelProfileType = profileType;
+        this._profiles.push(profile);
+        this._profilesIdMap[this._makeKey(profile.uid, typeId)] = profile;
+
+        if (profile.title.indexOf(UserInitiatedProfileName) !== 0) {
+            var profileTitleKey = this._makeKey(profile.title, typeId);
+            if (!(profileTitleKey in this._profileGroups))
+                this._profileGroups[profileTitleKey] = [];
+
+            var group = this._profileGroups[profileTitleKey];
+            group.push(profile);
+
+            if (group.length === 2) {
+                // Make a group TreeElement now that there are 2 profiles.
+                group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);
+
+                // Insert at the same index for the first profile of the group.
+                var index = sidebarParent.children.indexOf(group[0]._profilesTreeElement);
+                sidebarParent.insertChild(group._profilesTreeElement, index);
+
+                // Move the first profile to the group.
+                var selected = group[0]._profilesTreeElement.selected;
+                sidebarParent.removeChild(group[0]._profilesTreeElement);
+                group._profilesTreeElement.appendChild(group[0]._profilesTreeElement);
+                if (selected) {
+                    group[0]._profilesTreeElement.select();
+                    group[0]._profilesTreeElement.reveal();
+                }
+
+                group[0]._profilesTreeElement.small = true;
+                group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);
+
+                this.sidebarTreeElement.addStyleClass("some-expandable");
+            }
+
+            if (group.length >= 2) {
+                sidebarParent = group._profilesTreeElement;
+                alternateTitle = WebInspector.UIString("Run %d", group.length);
+                small = true;
+            }
+        }
+
+        var profileTreeElement = profileType.createSidebarTreeElementForProfile(profile);
+        profile.sideBarElement = profileTreeElement;
+        profileTreeElement.small = small;
+        if (alternateTitle)
+            profileTreeElement.mainTitle = alternateTitle;
+        profile._profilesTreeElement = profileTreeElement;
+
+        sidebarParent.appendChild(profileTreeElement);
+        if (!profile.isTemporary) {
+            this.welcomeView.hide();
+            if (!this.visibleView)
+                this.showProfile(profile);
+            this.dispatchEventToListeners("profile added");
+        }
+    },
+
+    _removeProfileHeader: function(profile)
+    {
+        var typeId = profile.typeId;
+        var profileType = this.getProfileType(typeId);
+        var sidebarParent = profileType.treeElement;
+
+        for (var i = 0; i < this._profiles.length; ++i) {
+            if (this._profiles[i].uid === profile.uid) {
+                profile = this._profiles[i];
+                this._profiles.splice(i, 1);
+                break;
+            }
+        }
+        delete this._profilesIdMap[this._makeKey(profile.uid, typeId)];
+
+        var profileTitleKey = this._makeKey(profile.title, typeId);
+        delete this._profileGroups[profileTitleKey];
+
+        sidebarParent.removeChild(profile._profilesTreeElement);
+
+        if (!profile.isTemporary)
+            InspectorBackend.removeProfile(profile.typeId, profile.uid);
+
+        // No other item will be selected if there aren't any other profiles, so
+        // make sure that view gets cleared when the last profile is removed.
+        if (!this._profiles.length)
+            this.closeVisibleView();
+    },
+
+    showProfile: function(profile)
+    {
+        if (!profile || profile.isTemporary)
+            return;
+
+        this.closeVisibleView();
+
+        var view = profile.__profilesPanelProfileType.viewForProfile(profile);
+
+        view.show(this.profileViews);
+
+        profile._profilesTreeElement.select(true);
+        profile._profilesTreeElement.reveal();
+
+        this.visibleView = view;
+
+        this.profileViewStatusBarItemsContainer.removeChildren();
+
+        var statusBarItems = view.statusBarItems;
+        if (statusBarItems)
+            for (var i = 0; i < statusBarItems.length; ++i)
+                this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+    },
+
+    getProfiles: function(typeId)
+    {
+        var result = [];
+        var profilesCount = this._profiles.length;
+        for (var i = 0; i < profilesCount; ++i) {
+            var profile = this._profiles[i];
+            if (!profile.isTemporary && profile.typeId === typeId)
+                result.push(profile);
+        }
+        return result;
+    },
+
+    hasTemporaryProfile: function(typeId)
+    {
+        var profilesCount = this._profiles.length;
+        for (var i = 0; i < profilesCount; ++i)
+            if (this._profiles[i].typeId === typeId && this._profiles[i].isTemporary)
+                return true;
+        return false;
+    },
+
+    hasProfile: function(profile)
+    {
+        return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)];
+    },
+
+    loadHeapSnapshot: function(uid, callback)
+    {
+        var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
+        if (!profile)
+            return;
+
+        if (profile._loaded)
+            callback(profile);
+        else if (profile._is_loading)
+            profile._callbacks.push(callback);
+        else {
+            profile._is_loading = true;
+            profile._callbacks = [callback];
+            profile._json = "";
+            profile.sideBarElement.subtitle = WebInspector.UIString("Loading…");
+            InspectorBackend.getProfile(profile.typeId, profile.uid);
+        }
+    },
+
+    _addHeapSnapshotChunk: function(uid, chunk)
+    {
+        var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
+        if (!profile || profile._loaded || !profile._is_loading)
+            return;
+
+        profile._json += chunk;
+    },
+
+    _finishHeapSnapshot: function(uid)
+    {
+        var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
+        if (!profile || profile._loaded || !profile._is_loading)
+            return;
+
+        var callbacks = profile._callbacks;
+        delete profile._callbacks;
+        profile.sideBarElement.subtitle = WebInspector.UIString("Parsing…");
+        window.setTimeout(doParse, 0);
+
+        function doParse()
+        {
+            var loadedSnapshot = JSON.parse(profile._json);
+            delete profile._json;
+            delete profile._is_loading;
+            profile._loaded = true;
+            profile.sideBarElement.subtitle = "";
+            if (!Preferences.detailedHeapProfiles)
+                WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
+            else
+                WebInspector.DetailedHeapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
+            for (var i = 0; i < callbacks.length; ++i)
+                callbacks[i](profile);
+        }
+    },
+
+    showView: function(view)
+    {
+        this.showProfile(view.profile);
+    },
+
+    getProfileType: function(typeId)
+    {
+        return this._profileTypesByIdMap[typeId];
+    },
+
+    showProfileForURL: function(url)
+    {
+        var match = url.match(WebInspector.ProfileType.URLRegExp);
+        if (!match)
+            return;
+        this.showProfile(this._profilesIdMap[this._makeKey(match[3], match[1])]);
+    },
+
+    updateProfileTypeButtons: function()
+    {
+        for (var typeId in this._profileTypeButtonsByIdMap) {
+            var buttonElement = this._profileTypeButtonsByIdMap[typeId];
+            var profileType = this.getProfileType(typeId);
+            buttonElement.className = profileType.buttonStyle;
+            buttonElement.title = profileType.buttonTooltip;
+            // FIXME: Apply profileType.buttonCaption once captions are added to button controls.
+        }
+    },
+
+    closeVisibleView: function()
+    {
+        if (this.visibleView)
+            this.visibleView.hide();
+        delete this.visibleView;
+    },
+
+    displayTitleForProfileLink: function(title, typeId)
+    {
+        title = unescape(title);
+        if (title.indexOf(UserInitiatedProfileName) === 0) {
+            title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1));
+        } else {
+            var titleKey = this._makeKey(title, typeId);
+            if (!(titleKey in this._profileGroupsForLinks))
+                this._profileGroupsForLinks[titleKey] = 0;
+
+            var groupNumber = ++this._profileGroupsForLinks[titleKey];
+
+            if (groupNumber > 2)
+                // The title is used in the console message announcing that a profile has started so it gets
+                // incremented twice as often as it's displayed
+                title += " " + WebInspector.UIString("Run %d", (groupNumber + 1) / 2);
+        }
+        
+        return title;
+    },
+
+    get searchableViews()
+    {
+        var views = [];
+
+        const visibleView = this.visibleView;
+        if (visibleView && visibleView.performSearch)
+            views.push(visibleView);
+
+        var profilesLength = this._profiles.length;
+        for (var i = 0; i < profilesLength; ++i) {
+            var profile = this._profiles[i];
+            var view = profile.__profilesPanelProfileType.viewForProfile(profile);
+            if (!view.performSearch || view === visibleView)
+                continue;
+            views.push(view);
+        }
+
+        return views;
+    },
+
+    searchMatchFound: function(view, matches)
+    {
+        view.profile._profilesTreeElement.searchMatches = matches;
+    },
+
+    searchCanceled: function(startingNewSearch)
+    {
+        WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+        if (!this._profiles)
+            return;
+
+        for (var i = 0; i < this._profiles.length; ++i) {
+            var profile = this._profiles[i];
+            profile._profilesTreeElement.searchMatches = 0;
+        }
+    },
+
+    _updateInterface: function()
+    {
+        // FIXME: Replace ProfileType-specific button visibility changes by a single ProfileType-agnostic "combo-button" visibility change.
+        if (this._profilerEnabled) {
+            this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
+            this.enableToggleButton.toggled = true;
+            for (var typeId in this._profileTypeButtonsByIdMap)
+                this._profileTypeButtonsByIdMap[typeId].removeStyleClass("hidden");
+            this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
+            this.clearResultsButton.element.removeStyleClass("hidden");
+            this.panelEnablerView.visible = false;
+        } else {
+            this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
+            this.enableToggleButton.toggled = false;
+            for (var typeId in this._profileTypeButtonsByIdMap)
+                this._profileTypeButtonsByIdMap[typeId].addStyleClass("hidden");
+            this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
+            this.clearResultsButton.element.addStyleClass("hidden");
+            this.panelEnablerView.visible = true;
+        }
+    },
+
+    _enableProfiling: function()
+    {
+        if (this._profilerEnabled)
+            return;
+        this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
+    },
+
+    _toggleProfiling: function(optionalAlways)
+    {
+        if (this._profilerEnabled) {
+            WebInspector.settings.profilerEnabled = false;
+            InspectorBackend.disableProfiler(true);
+        } else {
+            WebInspector.settings.profilerEnabled = !!optionalAlways;
+            InspectorBackend.enableProfiler();
+        }
+    },
+
+    _populateProfiles: function()
+    {
+        if (!this._profilerEnabled || this._profilesWereRequested)
+            return;
+
+        function populateCallback(profileHeaders) {
+            profileHeaders.sort(function(a, b) { return a.uid - b.uid; });
+            var profileHeadersLength = profileHeaders.length;
+            for (var i = 0; i < profileHeadersLength; ++i)
+                if (!this.hasProfile(profileHeaders[i]))
+                   this._addProfileHeader(profileHeaders[i]);
+        }
+
+        InspectorBackend.getProfileHeaders(populateCallback.bind(this));
+
+        this._profilesWereRequested = true;
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this.welcomeView.element.style.left = width + "px";
+        this.profileViews.style.left = width + "px";
+        this.profileViewStatusBarItemsContainer.style.left = Math.max(155, width) + "px";
+        this.resize();
+    },
+
+    _setRecordingProfile: function(isProfiling)
+    {
+        this.getProfileType(WebInspector.CPUProfileType.TypeId).setRecordingProfile(isProfiling);
+        if (this.hasTemporaryProfile(WebInspector.CPUProfileType.TypeId) !== isProfiling) {
+            if (!this._temporaryRecordingProfile) {
+                this._temporaryRecordingProfile = {
+                    typeId: WebInspector.CPUProfileType.TypeId,
+                    title: WebInspector.UIString("Recording…"),
+                    uid: -1,
+                    isTemporary: true
+                };
+            }
+            if (isProfiling)
+                this._addProfileHeader(this._temporaryRecordingProfile);
+            else
+                this._removeProfileHeader(this._temporaryRecordingProfile);
+        }
+        this.updateProfileTypeButtons();
+    },
+
+    takeHeapSnapshot: function(detailed)
+    {
+        if (!this.hasTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
+            if (!this._temporaryTakingSnapshot) {
+                this._temporaryTakingSnapshot = {
+                    typeId: WebInspector.HeapSnapshotProfileType.TypeId,
+                    title: WebInspector.UIString("Snapshotting…"),
+                    uid: -1,
+                    isTemporary: true
+                };
+            }
+            this._addProfileHeader(this._temporaryTakingSnapshot);
+        }
+        InspectorBackend.takeHeapSnapshot(detailed);
+    },
+
+    _reportHeapSnapshotProgress: function(done, total)
+    {
+        if (this.hasTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
+            this._temporaryTakingSnapshot.sideBarElement.subtitle = WebInspector.UIString("%.2f%%", (done / total) * 100);
+            if (done >= total)
+                this._removeProfileHeader(this._temporaryTakingSnapshot);
+        }
+    }
+}
+
+WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+
+WebInspector.ProfilerDispatcher = function(profiler)
+{
+    this._profiler = profiler;
+}
+
+WebInspector.ProfilerDispatcher.prototype = {
+    profilerWasEnabled: function()
+    {
+        this._profiler._profilerWasEnabled();
+    },
+
+    profilerWasDisabled: function()
+    {
+        this._profiler._profilerWasDisabled();
+    },
+
+    resetProfiles: function()
+    {
+        this._profiler._reset();
+    },
+
+    addProfileHeader: function(profile)
+    {
+        this._profiler._addProfileHeader(profile);
+    },
+
+    addHeapSnapshotChunk: function(uid, chunk)
+    {
+        this._profiler._addHeapSnapshotChunk(uid, chunk);
+    },
+
+    finishHeapSnapshot: function(uid)
+    {
+        this._profiler._finishHeapSnapshot(uid);
+    },
+
+    setRecordingProfile: function(isProfiling)
+    {
+        this._profiler._setRecordingProfile(isProfiling);
+    },
+
+    reportHeapSnapshotProgress: function(done, total)
+    {
+        this._profiler._reportHeapSnapshotProgress(done, total);
+    }
+}
+
+WebInspector.ProfileSidebarTreeElement = function(profile, titleFormat, className)
+{
+    this.profile = profile;
+    this._titleFormat = titleFormat;
+
+    if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+        this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);
+
+    WebInspector.SidebarTreeElement.call(this, className, "", "", profile, false);
+
+    this.refreshTitles();
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype = {
+    onselect: function()
+    {
+        this.treeOutline.panel.showProfile(this.profile);
+    },
+
+    ondelete: function()
+    {
+        this.treeOutline.panel._removeProfileHeader(this.profile);
+        return true;
+    },
+
+    get mainTitle()
+    {
+        if (this._mainTitle)
+            return this._mainTitle;
+        if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+            return WebInspector.UIString(this._titleFormat, this._profileNumber);
+        return this.profile.title;
+    },
+
+    set mainTitle(x)
+    {
+        this._mainTitle = x;
+        this.refreshTitles();
+    },
+
+    set searchMatches(matches)
+    {
+        if (!matches) {
+            if (!this.bubbleElement)
+                return;
+            this.bubbleElement.removeStyleClass("search-matches");
+            this.bubbleText = "";
+            return;
+        }
+
+        this.bubbleText = matches;
+        this.bubbleElement.addStyleClass("search-matches");
+    }
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
+{
+    WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype = {
+    onselect: function()
+    {
+        if (this.children.length > 0)
+            WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
+    }
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSection.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSection.js
new file mode 100644
index 0000000..88cb1a2
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSection.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Google Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSection = function(title, subtitle)
+{
+    WebInspector.Section.call(this, title, subtitle);
+
+    this.headerElement.addStyleClass("monospace");
+    this.propertiesElement = document.createElement("ol");
+    this.propertiesElement.className = "properties properties-tree monospace";
+    this.propertiesElement.tabIndex = 0;
+    this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
+    this.propertiesTreeOutline.section = this;
+
+    this.element.appendChild(this.propertiesElement);
+}
+
+WebInspector.PropertiesSection.prototype.__proto__ = WebInspector.Section.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSidebarPane.js
new file mode 100644
index 0000000..a1e37bc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/PropertiesSidebarPane.js
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties"));
+}
+
+WebInspector.PropertiesSidebarPane.prototype = {
+    update: function(node)
+    {
+        var body = this.bodyElement;
+
+        if (!node) {
+            body.removeChildren();
+            this.sections = [];
+            return;
+        }
+
+        function callback(prototypes)
+        {
+            var body = this.bodyElement;
+            body.removeChildren();
+            this.sections = [];
+
+            // Get array of prototype user-friendly names.
+            for (var i = 0; i < prototypes.length; ++i) {
+                var prototype = WebInspector.RemoteObject.fromPayload(prototypes[i]);
+                var title = prototype.description;
+                if (title.match(/Prototype$/))
+                    title = title.replace(/Prototype$/, "");
+                var section = new WebInspector.ObjectPropertiesSection(prototype, title);
+                this.sections.push(section);
+                body.appendChild(section.element);
+            }
+        }
+        InspectorBackend.getNodePrototypes(node.id, callback.bind(this));
+    }
+}
+
+WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/RemoteObject.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/RemoteObject.js
new file mode 100644
index 0000000..10af2e3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/RemoteObject.js
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.RemoteObject = function(objectId, type, description, hasChildren)
+{
+    this._objectId = objectId;
+    this._type = type;
+    this._description = description;
+    this._hasChildren = hasChildren;
+}
+
+WebInspector.RemoteObject.fromPrimitiveValue = function(value)
+{
+    return new WebInspector.RemoteObject(null, typeof value, value);
+}
+
+WebInspector.RemoteObject.fromLocalObject = function(value)
+{
+    return new WebInspector.LocalJSONObject(value);
+}
+
+WebInspector.RemoteObject.resolveNode = function(node, callback)
+{
+    function mycallback(object)
+    {
+        callback(object ? WebInspector.RemoteObject.fromPayload(object) : null);
+    }
+    InspectorBackend.resolveNode(node.id, mycallback);
+}
+
+WebInspector.RemoteObject.fromPayload = function(payload)
+{
+    if (typeof payload === "object")
+        return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.description, payload.hasChildren);
+    // FIXME: make sure we only get here with real payloads in the new DebuggerAgent.js.
+    return payload;
+}
+
+WebInspector.RemoteObject.type = function(remoteObject)
+{
+    if (remoteObject === null)
+        return "null";
+
+    var type = typeof remoteObject;
+    if (type !== "object" && type !== "function")
+        return type;
+
+    return remoteObject.type;
+}
+
+WebInspector.RemoteObject.prototype = {
+    get objectId()
+    {
+        return this._objectId;
+    },
+
+    get type()
+    {
+        return this._type;
+    },
+
+    get description()
+    {
+        return this._description;
+    },
+
+    get hasChildren()
+    {
+        return this._hasChildren;
+    },
+
+    isError: function()
+    {
+        return this._type === "error";
+    },
+
+    getOwnProperties: function(abbreviate, callback)
+    {
+        this.getProperties(false, abbreviate, callback);
+    },
+
+    getProperties: function(ignoreHasOwnProperty, abbreviate, callback)
+    {
+        if (!this._objectId) {
+            callback([]);
+            return;
+        }
+        function remoteObjectBinder(properties)
+        {
+            for (var i = 0; properties && i < properties.length; ++i)
+                properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value);
+            callback(properties);
+        }
+        InspectorBackend.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder);
+    },
+
+    setPropertyValue: function(name, value, callback)
+    {
+        if (!this._objectId) {
+            callback(false);
+            return;
+        }
+        InspectorBackend.setPropertyValue(this._objectId, name, value, callback);
+    },
+
+    pushNodeToFrontend: function(callback)
+    {
+        InspectorBackend.pushNodeToFrontend(this._objectId, callback);
+    }
+}
+
+WebInspector.RemoteObjectProperty = function(name, value)
+{
+    this.name = name;
+    this.value = value;
+}
+
+// The below is a wrapper around a local object that provides an interface comaptible
+// with RemoteObject, to be used by the UI code (primarily ObjectPropertiesSection).
+// Note that only JSON-compliant objects are currently supported, as there's no provision
+// for traversing prototypes, extracting class names via constuctor, handling properties
+// or functions.
+
+WebInspector.LocalJSONObject = function(value)
+{
+    this._value = value;
+}
+
+WebInspector.LocalJSONObject.prototype = {
+    get description()
+    {
+        var type = this.type;
+        switch (type) {
+            case "array":
+                return "[" + this._value.length + "]";
+            case "object":
+                return this.hasChildren ? "{...}" : "{ }";
+            default:
+                return JSON.stringify(this._value);
+        }
+    },
+
+    get type()
+    {
+        if (this._value === null)
+            return "null";
+        if (this._value instanceof Array)
+            return "array";
+        return typeof this._value;
+    },
+
+    get hasChildren()
+    {
+        return typeof this._value === "object" && this._value !== null && Object.keys(this._value).length;
+    },
+
+    getOwnProperties: function(abbreviate, callback)
+    {
+        return this.getProperties(false, abbreviate, callback);
+    },
+
+    getProperties: function(ignoreHasOwnProperty, abbreviate, callback)
+    {
+        function buildProperty(propName)
+        {
+            return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName]));
+        }
+        callback(Object.keys(this._value).map(buildProperty.bind(this)));
+    },
+
+    isError: function()
+    {
+        return false;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Resource.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Resource.js
new file mode 100644
index 0000000..6cf5b9c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Resource.js
@@ -0,0 +1,748 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+WebInspector.Resource = function(identifier, url)
+{
+    this.identifier = identifier;
+    this.url = url;
+    this._startTime = -1;
+    this._endTime = -1;
+    this._category = WebInspector.resourceCategories.other;
+    this._pendingContentCallbacks = [];
+    this._responseHeadersSize = 0;
+}
+
+// Keep these in sync with WebCore::InspectorResource::Type
+WebInspector.Resource.Type = {
+    Document:   0,
+    Stylesheet: 1,
+    Image:      2,
+    Font:       3,
+    Script:     4,
+    XHR:        5,
+    WebSocket:  7,
+    Other:      8,
+
+    isTextType: function(type)
+    {
+        return (type === this.Document) || (type === this.Stylesheet) || (type === this.Script) || (type === this.XHR);
+    },
+
+    toUIString: function(type)
+    {
+        switch (type) {
+            case this.Document:
+                return WebInspector.UIString("Document");
+            case this.Stylesheet:
+                return WebInspector.UIString("Stylesheet");
+            case this.Image:
+                return WebInspector.UIString("Image");
+            case this.Font:
+                return WebInspector.UIString("Font");
+            case this.Script:
+                return WebInspector.UIString("Script");
+            case this.XHR:
+                return WebInspector.UIString("XHR");
+            case this.WebSocket:
+                return WebInspector.UIString("WebSocket");
+            case this.Other:
+            default:
+                return WebInspector.UIString("Other");
+        }
+    },
+
+    // Returns locale-independent string identifier of resource type (primarily for use in extension API).
+    // The IDs need to be kept in sync with webInspector.resoureces.Types object in ExtensionAPI.js.
+    toString: function(type)
+    {
+        switch (type) {
+            case this.Document:
+                return "document";
+            case this.Stylesheet:
+                return "stylesheet";
+            case this.Image:
+                return "image";
+            case this.Font:
+                return "font";
+            case this.Script:
+                return "script";
+            case this.XHR:
+                return "xhr";
+            case this.WebSocket:
+                return "websocket";
+            case this.Other:
+            default:
+                return "other";
+        }
+    }
+}
+
+WebInspector.Resource.prototype = {
+    get url()
+    {
+        return this._url;
+    },
+
+    set url(x)
+    {
+        if (this._url === x)
+            return;
+
+        this._url = x;
+        delete this._parsedQueryParameters;
+
+        var parsedURL = x.asParsedURL();
+        this.domain = parsedURL ? parsedURL.host : "";
+        this.path = parsedURL ? parsedURL.path : "";
+        this.lastPathComponent = "";
+        if (parsedURL && parsedURL.path) {
+            // First cut the query params.
+            var path = parsedURL.path;
+            var indexOfQuery = path.indexOf("?");
+            if (indexOfQuery !== -1)
+                path = path.substring(0, indexOfQuery);
+
+            // Then take last path component.
+            var lastSlashIndex = path.lastIndexOf("/");
+            if (lastSlashIndex !== -1)
+                this.lastPathComponent = path.substring(lastSlashIndex + 1);
+        }
+        this.lastPathComponentLowerCase = this.lastPathComponent.toLowerCase();
+    },
+
+    get documentURL()
+    {
+        return this._documentURL;
+    },
+
+    set documentURL(x)
+    {
+        this._documentURL = x;
+    },
+
+    get displayName()
+    {
+        if (this._displayName)
+            return this._displayName;
+        this._displayName = this.lastPathComponent;
+        if (!this._displayName)
+            this._displayName = this.displayDomain;
+        if (!this._displayName && this.url)
+            this._displayName = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+        if (this._displayName === "/")
+            this._displayName = this.url;
+        return this._displayName;
+    },
+
+    get displayDomain()
+    {
+        // WebInspector.Database calls this, so don't access more than this.domain.
+        if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain)))
+            return this.domain;
+        return "";
+    },
+
+    get startTime()
+    {
+        return this._startTime || -1;
+    },
+
+    set startTime(x)
+    {
+        this._startTime = x;
+    },
+
+    get responseReceivedTime()
+    {
+        return this._responseReceivedTime || -1;
+    },
+
+    set responseReceivedTime(x)
+    {
+        this._responseReceivedTime = x;
+    },
+
+    get endTime()
+    {
+        return this._endTime || -1;
+    },
+
+    set endTime(x)
+    {
+        if (this.timing && this.timing.requestTime) {
+            // Check against accurate responseReceivedTime.
+            this._endTime = Math.max(x, this.responseReceivedTime);
+        } else {
+            // Prefer endTime since it might be from the network stack.
+            this._endTime = x;
+            if (this._responseReceivedTime > x)
+                this._responseReceivedTime = x;
+        }
+    },
+
+    get duration()
+    {
+        if (this._endTime === -1 || this._startTime === -1)
+            return -1;
+        return this._endTime - this._startTime;
+    },
+
+    get latency()
+    {
+        if (this._responseReceivedTime === -1 || this._startTime === -1)
+            return -1;
+        return this._responseReceivedTime - this._startTime;
+    },
+
+    get receiveDuration()
+    {
+        if (this._endTime === -1 || this._responseReceivedTime === -1)
+            return -1;
+        return this._endTime - this._responseReceivedTime;
+    },
+
+    get resourceSize()
+    {
+        return this._resourceSize || 0;
+    },
+
+    set resourceSize(x)
+    {
+        this._resourceSize = x;
+    },
+
+    get transferSize()
+    {
+        if (this.cached)
+            return 0;
+        if (this.statusCode === 304) // Not modified
+            return this._responseHeadersSize;
+        // FIXME: We prefer using Content-Length over resourceSize as
+        // resourceSize may differ from actual transfer size if platform's
+        // network stack performed decoding (e.g. gzip decompression).
+        // The Content-Length, though, is expected to come from raw
+        // response headers and will reflect actual transfer length.
+        // This won't work for chunked content encoding, so fall back to
+        // resourceSize when we don't have Content-Length. This still won't
+        // work for chunks with non-trivial encodings. We need a way to
+        // get actaul transfer size from the network stack.
+        var bodySize = Number(this.responseHeaders["Content-Length"] || this.resourceSize);
+        return this._responseHeadersSize + bodySize;
+    },
+
+    get expectedContentLength()
+    {
+        return this._expectedContentLength || 0;
+    },
+
+    set expectedContentLength(x)
+    {
+        this._expectedContentLength = x;
+    },
+
+    get finished()
+    {
+        return this._finished;
+    },
+
+    set finished(x)
+    {
+        if (this._finished === x)
+            return;
+
+        this._finished = x;
+
+        if (x) {
+            this._checkWarnings();
+            this.dispatchEventToListeners("finished");
+            if (this._pendingContentCallbacks.length)
+                this._innerRequestContent();
+        }
+    },
+
+    get failed()
+    {
+        return this._failed;
+    },
+
+    set failed(x)
+    {
+        this._failed = x;
+    },
+
+    get category()
+    {
+        return this._category;
+    },
+
+    set category(x)
+    {
+        this._category = x;
+    },
+
+    get cached()
+    {
+        return this._cached;
+    },
+
+    set cached(x)
+    {
+        this._cached = x;
+        if (x)
+            delete this._timing;
+    },
+
+    get timing()
+    {
+        return this._timing;
+    },
+
+    set timing(x)
+    {
+        if (x && !this._cached) {
+            // Take startTime and responseReceivedTime from timing data for better accuracy.
+            // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis.
+            this._startTime = x.requestTime;
+            this._responseReceivedTime = x.requestTime + x.receiveHeadersEnd / 1000.0;
+
+            this._timing = x;
+            this.dispatchEventToListeners("timing changed");
+        }
+    },
+
+    get mimeType()
+    {
+        return this._mimeType;
+    },
+
+    set mimeType(x)
+    {
+        this._mimeType = x;
+    },
+
+    get type()
+    {
+        return this._type;
+    },
+
+    set type(x)
+    {
+        if (this._type === x)
+            return;
+
+        this._type = x;
+
+        switch (x) {
+            case WebInspector.Resource.Type.Document:
+                this.category = WebInspector.resourceCategories.documents;
+                break;
+            case WebInspector.Resource.Type.Stylesheet:
+                this.category = WebInspector.resourceCategories.stylesheets;
+                break;
+            case WebInspector.Resource.Type.Script:
+                this.category = WebInspector.resourceCategories.scripts;
+                break;
+            case WebInspector.Resource.Type.Image:
+                this.category = WebInspector.resourceCategories.images;
+                break;
+            case WebInspector.Resource.Type.Font:
+                this.category = WebInspector.resourceCategories.fonts;
+                break;
+            case WebInspector.Resource.Type.XHR:
+                this.category = WebInspector.resourceCategories.xhr;
+                break;
+            case WebInspector.Resource.Type.WebSocket:
+                this.category = WebInspector.resourceCategories.websockets;
+                break;
+            case WebInspector.Resource.Type.Other:
+            default:
+                this.category = WebInspector.resourceCategories.other;
+                break;
+        }
+    },
+
+    get requestHeaders()
+    {
+        return this._requestHeaders || {};
+    },
+
+    set requestHeaders(x)
+    {
+        this._requestHeaders = x;
+        delete this._sortedRequestHeaders;
+        delete this._requestCookies;
+
+        this.dispatchEventToListeners("requestHeaders changed");
+    },
+
+    get sortedRequestHeaders()
+    {
+        if (this._sortedRequestHeaders !== undefined)
+            return this._sortedRequestHeaders;
+
+        this._sortedRequestHeaders = [];
+        for (var key in this.requestHeaders)
+            this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]});
+        this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+        return this._sortedRequestHeaders;
+    },
+
+    requestHeaderValue: function(headerName)
+    {
+        return this._headerValue(this.requestHeaders, headerName);
+    },
+
+    get requestCookies()
+    {
+        if (!this._requestCookies)
+            this._requestCookies = WebInspector.CookieParser.parseCookie(this.requestHeaderValue("Cookie"));
+        return this._requestCookies;
+    },
+
+    get requestFormData()
+    {
+        return this._requestFormData;
+    },
+
+    set requestFormData(x)
+    {
+        this._requestFormData = x;
+        delete this._parsedFormParameters;
+    },
+
+    get responseHeaders()
+    {
+        return this._responseHeaders || {};
+    },
+
+    set responseHeaders(x)
+    {
+        this._responseHeaders = x;
+        // FIXME: we should take actual headers size from network stack, when possible.
+        this._responseHeadersSize = this._headersSize(x);
+        delete this._sortedResponseHeaders;
+        delete this._responseCookies;
+
+        this.dispatchEventToListeners("responseHeaders changed");
+    },
+
+    get sortedResponseHeaders()
+    {
+        if (this._sortedResponseHeaders !== undefined)
+            return this._sortedResponseHeaders;
+
+        this._sortedResponseHeaders = [];
+        for (var key in this.responseHeaders)
+            this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]});
+        this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+        return this._sortedResponseHeaders;
+    },
+
+    responseHeaderValue: function(headerName)
+    {
+        return this._headerValue(this.responseHeaders, headerName);
+    },
+
+    get responseCookies()
+    {
+        if (!this._responseCookies)
+            this._responseCookies = WebInspector.CookieParser.parseSetCookie(this.responseHeaderValue("Set-Cookie"));
+        return this._responseCookies;
+    },
+
+    get queryParameters()
+    {
+        if (this._parsedQueryParameters)
+            return this._parsedQueryParameters;
+        var queryString = this.url.split("?", 2)[1];
+        if (!queryString)
+            return;
+        this._parsedQueryParameters = this._parseParameters(queryString);
+        return this._parsedQueryParameters;
+    },
+
+    get formParameters()
+    {
+        if (this._parsedFormParameters)
+            return this._parsedFormParameters;
+        if (!this.requestFormData)
+            return;
+        var requestContentType = this.requestHeaderValue("Content-Type");
+        if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
+            return;
+        this._parsedFormParameters = this._parseParameters(this.requestFormData);
+        return this._parsedFormParameters;
+    },
+
+    _parseParameters: function(queryString)
+    {
+        function parseNameValue(pair)
+        {
+            var parameter = {};
+            var splitPair = pair.split("=", 2);
+
+            parameter.name = splitPair[0];
+            if (splitPair.length === 1)
+                parameter.value = "";
+            else
+                parameter.value = splitPair[1];
+            return parameter;
+        }
+        return queryString.split("&").map(parseNameValue);
+    },
+
+    _headerValue: function(headers, headerName)
+    {
+        headerName = headerName.toLowerCase();
+        for (var header in headers) {
+            if (header.toLowerCase() === headerName)
+                return headers[header];
+        }
+    },
+
+    _headersSize: function(headers)
+    {
+        var size = 0;
+        for (var header in headers)
+            size += header.length + headers[header].length + 3; // _typical_ overhead per herader is ": ".length + "\n".length.
+        return size;
+    },
+
+    get errors()
+    {
+        return this._errors || 0;
+    },
+
+    set errors(x)
+    {
+        this._errors = x;
+        this.dispatchEventToListeners("errors-warnings-updated");
+    },
+
+    get warnings()
+    {
+        return this._warnings || 0;
+    },
+
+    set warnings(x)
+    {
+        this._warnings = x;
+        this.dispatchEventToListeners("errors-warnings-updated");
+    },
+
+    clearErrorsAndWarnings: function()
+    {
+        this._warnings = 0;
+        this._errors = 0;
+        this.dispatchEventToListeners("errors-warnings-updated");
+    },
+
+    _mimeTypeIsConsistentWithType: function()
+    {
+        // If status is an error, content is likely to be of an inconsistent type,
+        // as it's going to be an error message. We do not want to emit a warning
+        // for this, though, as this will already be reported as resource loading failure.
+        if (this.statusCode >= 400)
+            return true;
+
+        if (typeof this.type === "undefined"
+            || this.type === WebInspector.Resource.Type.Other
+            || this.type === WebInspector.Resource.Type.XHR
+            || this.type === WebInspector.Resource.Type.WebSocket)
+            return true;
+
+        if (!this.mimeType)
+            return true; // Might be not known for cached resources with null responses.
+
+        if (this.mimeType in WebInspector.MIMETypes)
+            return this.type in WebInspector.MIMETypes[this.mimeType];
+
+        return false;
+    },
+
+    _checkWarnings: function()
+    {
+        for (var warning in WebInspector.Warnings)
+            this._checkWarning(WebInspector.Warnings[warning]);
+    },
+
+    _checkWarning: function(warning)
+    {
+        var msg;
+        switch (warning.id) {
+            case WebInspector.Warnings.IncorrectMIMEType.id:
+                if (!this._mimeTypeIsConsistentWithType())
+                    msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+                        WebInspector.ConsoleMessage.MessageType.Log,
+                        WebInspector.ConsoleMessage.MessageLevel.Warning,
+                        -1,
+                        this.url,
+                        1,
+                        String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message, WebInspector.Resource.Type.toUIString(this.type), this.mimeType),
+                        null,
+                        null);
+                break;
+        }
+
+        if (msg)
+            WebInspector.console.addMessage(msg);
+    },
+
+    get content()
+    {
+        return this._content;
+    },
+
+    get contentTimestamp()
+    {
+        return this._contentTimestamp;
+    },
+
+    setInitialContent: function(content)
+    {
+        this._content = content;
+    },
+
+    isLocallyModified: function()
+    {
+        return !!this._baseRevision;
+    },
+
+    setContent: function(newContent, onRevert)
+    {
+        var revisionResource = new WebInspector.Resource(null, this.url);
+        revisionResource.type = this.type;
+        revisionResource.loader = this.loader;
+        revisionResource.timestamp = this.timestamp;
+        revisionResource._content = this._content;
+        revisionResource._actualResource = this;
+        revisionResource._fireOnRevert = onRevert;
+
+        if (this.finished)
+            revisionResource.finished = true;
+        else {
+            function finished()
+            {
+                this.removeEventListener("finished", finished);
+                revisionResource.finished = true;
+            }
+            this.addEventListener("finished", finished.bind(this));
+        }
+
+        if (!this._baseRevision)
+            this._baseRevision = revisionResource;
+        else
+            revisionResource._baseRevision = this._baseRevision;
+
+        var data = { revision: revisionResource };
+        this._content = newContent;
+        this.timestamp = new Date();
+        this.dispatchEventToListeners("content-changed", data);
+    },
+
+    revertToThis: function()
+    {
+        if (!this._actualResource || !this._fireOnRevert)
+            return;
+
+        function callback(content)
+        {
+            if (content)
+                this._fireOnRevert(content);
+        }
+        this.requestContent(callback.bind(this));
+    },
+
+    get baseRevision()
+    {
+        return this._baseRevision;
+    },
+
+    requestContent: function(callback)
+    {
+        // We do not support content retrieval for WebSockets at the moment.
+        // Since WebSockets are potentially long-living, fail requests immediately
+        // to prevent caller blocking until resource is marked as finished.
+        if (this.type === WebInspector.Resource.Type.WebSocket) {
+            callback(null, null);
+            return;
+        }
+        if (typeof this._content !== "undefined") {
+            callback(this.content, this._contentEncoded);
+            return;
+        }
+        this._pendingContentCallbacks.push(callback);
+        if (this.finished)
+            this._innerRequestContent();
+    },
+
+    populateImageSource: function(image)
+    {
+        function onResourceContent()
+        {
+            image.src = this._contentURL();
+        }
+
+        if (Preferences.useDataURLForResourceImageIcons)
+            this.requestContent(onResourceContent.bind(this));
+        else
+            image.src = this.url;
+    },
+
+    _contentURL: function()
+    {
+        const maxDataUrlSize = 1024 * 1024;
+        // If resource content is not available or won't fit a data URL, fall back to using original URL.
+        if (this._content == null || this._content.length > maxDataUrlSize)
+            return this.url;
+
+        return "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content;
+    },
+
+    _innerRequestContent: function()
+    {
+        if (this._contentRequested)
+            return;
+        this._contentRequested = true;
+        this._contentEncoded = !WebInspector.Resource.Type.isTextType(this.type);
+
+        function onResourceContent(data)
+        {
+            this._content = data;
+            var callbacks = this._pendingContentCallbacks.slice();
+            for (var i = 0; i < callbacks.length; ++i)
+                callbacks[i](this._content, this._contentEncoded);
+            this._pendingContentCallbacks.length = 0;
+            delete this._contentRequested;
+        }
+        WebInspector.networkManager.requestContent(this, this._contentEncoded, onResourceContent.bind(this));
+    }
+}
+
+WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCategory.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCategory.js
new file mode 100644
index 0000000..43c7c2b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCategory.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceCategory = function(name, title, color)
+{
+    this.name = name;
+    this.title = title;
+    this.color = color;
+}
+
+WebInspector.ResourceCategory.prototype = {
+    toString: function()
+    {
+        return this.title;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCookiesView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCookiesView.js
new file mode 100644
index 0000000..b60b1b6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceCookiesView.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceCookiesView = function(resource)
+{
+    WebInspector.View.call(this);
+    this.element.addStyleClass("resource-cookies-view");
+
+    this._resource = resource;
+
+    resource.addEventListener("requestHeaders changed", this.show, this);
+    resource.addEventListener("responseHeaders changed", this.show, this);
+}
+
+WebInspector.ResourceCookiesView.prototype = {
+    show: function(parentElement)
+    {
+        if (!this._resource.requestCookies && !this._resource.responseCookies) {
+            if (!this._emptyMsgElement) {
+                this._emptyMsgElement = document.createElement("div");
+                this._emptyMsgElement.className = "storage-empty-view";
+                this._emptyMsgElement.textContent = WebInspector.UIString("This request has no cookies.");
+                this.element.appendChild(this._emptyMsgElement);
+            }
+            WebInspector.View.prototype.show.call(this, parentElement);
+            return;
+        }
+
+        if (this._emptyMsgElement)
+            this._emptyMsgElement.parentElement.removeChild(this._emptyMsgElement);
+
+        if (!this._cookiesTable) {
+            this._cookiesTable = new WebInspector.CookiesTable(null, true, true);
+            this._cookiesTable.addCookiesFolder(WebInspector.UIString("Request Cookies"), this._resource.requestCookies);
+            this._cookiesTable.addCookiesFolder(WebInspector.UIString("Response Cookies"), this._resource.responseCookies);
+            this.element.appendChild(this._cookiesTable.element);
+        }
+
+        WebInspector.View.prototype.show.call(this, parentElement);
+        this._cookiesTable.updateWidths();
+    }
+}
+
+WebInspector.ResourceCookiesView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceHeadersView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceHeadersView.js
new file mode 100644
index 0000000..e79078a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceHeadersView.js
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) IBM Corp. 2009  All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceHeadersView = function(resource)
+{
+    WebInspector.View.call(this);
+    this.element.addStyleClass("resource-headers-view");
+
+    this._resource = resource;
+
+    this._headersListElement = document.createElement("ol");
+    this._headersListElement.className = "outline-disclosure";
+    this.element.appendChild(this._headersListElement);
+
+    this._headersTreeOutline = new TreeOutline(this._headersListElement);
+    this._headersTreeOutline.expandTreeElementsWhenArrowing = true;
+
+    this._urlTreeElement = new TreeElement("", null, false);
+    this._urlTreeElement.selectable = false;
+    this._headersTreeOutline.appendChild(this._urlTreeElement);
+
+    this._requestMethodTreeElement = new TreeElement("", null, false);
+    this._requestMethodTreeElement.selectable = false;
+    this._headersTreeOutline.appendChild(this._requestMethodTreeElement);
+
+    this._statusCodeTreeElement = new TreeElement("", null, false);
+    this._statusCodeTreeElement.selectable = false;
+    this._headersTreeOutline.appendChild(this._statusCodeTreeElement);
+     
+    this._requestHeadersTreeElement = new TreeElement("", null, true);
+    this._requestHeadersTreeElement.expanded = true;
+    this._requestHeadersTreeElement.selectable = false;
+    this._headersTreeOutline.appendChild(this._requestHeadersTreeElement);
+
+    this._decodeHover = WebInspector.UIString("Double-Click to toggle between URL encoded and decoded formats");
+    this._decodeRequestParameters = true;
+
+    this._queryStringTreeElement = new TreeElement("", null, true);
+    this._queryStringTreeElement.expanded = true;
+    this._queryStringTreeElement.selectable = false;
+    this._queryStringTreeElement.hidden = true;
+    this._headersTreeOutline.appendChild(this._queryStringTreeElement);
+
+    this._formDataTreeElement = new TreeElement("", null, true);
+    this._formDataTreeElement.expanded = true;
+    this._formDataTreeElement.selectable = false;
+    this._formDataTreeElement.hidden = true;
+    this._headersTreeOutline.appendChild(this._formDataTreeElement);
+
+    this._requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true);
+    this._requestPayloadTreeElement.expanded = true;
+    this._requestPayloadTreeElement.selectable = false;
+    this._requestPayloadTreeElement.hidden = true;
+    this._headersTreeOutline.appendChild(this._requestPayloadTreeElement);
+
+    this._responseHeadersTreeElement = new TreeElement("", null, true);
+    this._responseHeadersTreeElement.expanded = true;
+    this._responseHeadersTreeElement.selectable = false;
+    this._headersTreeOutline.appendChild(this._responseHeadersTreeElement);
+
+    resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
+    resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
+    resource.addEventListener("finished", this._refreshHTTPInformation, this);
+
+    this._refreshURL();
+    this._refreshQueryString();
+    this._refreshRequestHeaders();
+    this._refreshResponseHeaders();
+    this._refreshHTTPInformation();
+}
+
+WebInspector.ResourceHeadersView.prototype = {
+
+    _refreshURL: function()
+    {
+        this._urlTreeElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Request URL") + ":</div>" +
+            "<div class=\"header-value source-code\">" + this._resource.url.escapeHTML() + "</div>";
+    },
+
+    _refreshQueryString: function()
+    {
+        var queryParameters = this._resource.queryParameters;
+        this._queryStringTreeElement.hidden = !queryParameters;
+        if (queryParameters)
+            this._refreshParms(WebInspector.UIString("Query String Parameters"), queryParameters, this._queryStringTreeElement);
+    },
+
+    _refreshFormData: function()
+    {
+        this._formDataTreeElement.hidden = true;
+        this._requestPayloadTreeElement.hidden = true;
+
+        var formData = this._resource.requestFormData;
+        if (!formData)
+            return;
+
+        var formParameters = this._resource.formParameters;
+        if (formParameters) {
+            this._formDataTreeElement.hidden = false;
+            this._refreshParms(WebInspector.UIString("Form Data"), formParameters, this._formDataTreeElement);
+        } else {
+            this._requestPayloadTreeElement.hidden = false;
+            this._refreshRequestPayload(formData);
+        }
+    },
+
+    _refreshRequestPayload: function(formData)
+    {
+        this._requestPayloadTreeElement.removeChildren();
+
+        var title = "<div class=\"raw-form-data header-value source-code\">" + formData.escapeHTML() + "</div>";
+        var parmTreeElement = new TreeElement(null, null, false);
+        parmTreeElement.titleHTML = title;
+        parmTreeElement.selectable = false;
+        this._requestPayloadTreeElement.appendChild(parmTreeElement);
+    },
+
+    _refreshParms: function(title, parms, parmsTreeElement)
+    {
+        parmsTreeElement.removeChildren();
+
+        parmsTreeElement.titleHTML = title + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", parms.length) + "</span>";
+
+        for (var i = 0; i < parms.length; ++i) {
+            var name = parms[i].name;
+            var value = parms[i].value;
+
+            var errorDecoding = false;
+            if (this._decodeRequestParameters) {
+                if (value.indexOf("%") >= 0) {
+                    try {
+                        value = decodeURIComponent(value);
+                    } catch(e) {
+                        errorDecoding = true;
+                    }
+                }
+                    
+                value = value.replace(/\+/g, " ");
+            }
+
+            valueEscaped = value.escapeHTML();
+            if (errorDecoding)
+                valueEscaped += " <span class=\"error-message\">" + WebInspector.UIString("(unable to decode value)").escapeHTML() + "</span>";
+
+            var title = "<div class=\"header-name\">" + name.escapeHTML() + ":</div>";
+            title += "<div class=\"header-value source-code\">" + valueEscaped + "</div>";
+
+            var parmTreeElement = new TreeElement(null, null, false);
+            parmTreeElement.titleHTML = title;
+            parmTreeElement.selectable = false;
+            parmTreeElement.tooltip = this._decodeHover;
+            parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this);
+            parmsTreeElement.appendChild(parmTreeElement);
+        }
+    },
+
+    _toggleURLdecoding: function(event)
+    {
+        this._decodeRequestParameters = !this._decodeRequestParameters;
+        this._refreshQueryString();
+        this._refreshFormData();
+    },
+
+    _getHeaderValue: function(headers, key)
+    {
+        var lowerKey = key.toLowerCase();
+        for (var testKey in headers) {
+            if (testKey.toLowerCase() === lowerKey)
+                return headers[testKey];
+        }
+    },
+
+    _refreshRequestHeaders: function()
+    {
+        var additionalRow = null;
+        if (typeof this._resource.webSocketRequestKey3 !== "undefined")
+            additionalRow = {header: "(Key3)", value: this._resource.webSocketRequestKey3};
+        this._refreshHeaders(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement);
+        this._refreshFormData();
+    },
+
+    _refreshResponseHeaders: function()
+    {
+        var additionalRow = null;
+        if (typeof this._resource.webSocketChallengeResponse !== "undefined")
+            additionalRow = {header: "(Challenge Response)", value: this._resource.webSocketChallengeResponse};
+        this._refreshHeaders(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement);
+    },
+
+    _refreshHTTPInformation: function()
+    {
+        var requestMethodElement = this._requestMethodTreeElement;
+        requestMethodElement.hidden = !this._resource.statusCode;
+        var statusCodeElement = this._statusCodeTreeElement;
+        statusCodeElement.hidden = !this._resource.statusCode;
+        var statusCodeImage = "";
+
+        if (this._resource.statusCode) {
+            var statusImageSource = "";
+            if (this._resource.statusCode < 300 || this._resource.statusCode === 304)
+                statusImageSource = "Images/successGreenDot.png";
+            else if (this._resource.statusCode < 400)
+                statusImageSource = "Images/warningOrangeDot.png";
+            else
+                statusImageSource = "Images/errorRedDot.png";
+
+            var statusTextEscaped = this._resource.statusCode + " " + this._resource.statusText.escapeHTML();
+            statusCodeImage = "<img class=\"resource-status-image\" src=\"" + statusImageSource + "\" title=\"" + statusTextEscaped + "\">";
+    
+            requestMethodElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Request Method") + ":</div>" +
+                "<div class=\"header-value source-code\">" + this._resource.requestMethod + "</div>";
+
+            statusCodeElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Status Code") + ":</div>" +
+                statusCodeImage + "<div class=\"header-value source-code\">" + statusTextEscaped + "</div>";
+        }
+    },
+    
+    _refreshHeaders: function(title, headers, additionalRow, headersTreeElement)
+    {
+        headersTreeElement.removeChildren();
+
+        var length = headers.length;
+        headersTreeElement.titleHTML = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>";
+        headersTreeElement.hidden = !length;
+
+        var length = headers.length;
+        for (var i = 0; i < length; ++i) {
+            var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
+            title += "<div class=\"header-value source-code\">" + headers[i].value.escapeHTML() + "</div>"
+
+            var headerTreeElement = new TreeElement(null, null, false);
+            headerTreeElement.titleHTML = title;
+            headerTreeElement.selectable = false;
+            headersTreeElement.appendChild(headerTreeElement);
+        }
+
+        if (additionalRow) {
+            var title = "<div class=\"header-name\">" + additionalRow.header.escapeHTML() + ":</div>";
+            title += "<div class=\"header-value source-code\">" + additionalRow.value.escapeHTML() + "</div>"
+
+            var headerTreeElement = new TreeElement(null, null, false);
+            headerTreeElement.titleHTML = title;
+            headerTreeElement.selectable = false;
+            headersTreeElement.appendChild(headerTreeElement);
+        }
+    }
+}
+
+WebInspector.ResourceHeadersView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTimingView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTimingView.js
new file mode 100644
index 0000000..04f22f8
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTimingView.js
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceTimingView = function(resource)
+{
+    WebInspector.View.call(this);
+    this.element.addStyleClass("resource-timing-view");
+
+    this._resource = resource;
+
+    resource.addEventListener("timing changed", this._refresh, this);
+}
+
+WebInspector.ResourceTimingView.prototype = {
+    show: function(parentElement)
+    {
+        if (!this._resource.timing) {
+            if (!this._emptyMsgElement) {
+                this._emptyMsgElement = document.createElement("div");
+                this._emptyMsgElement.className = "storage-empty-view";
+                this._emptyMsgElement.textContent = WebInspector.UIString("This request has no detailed timing info.");
+                this.element.appendChild(this._emptyMsgElement);
+            }
+            WebInspector.View.prototype.show.call(this, parentElement);
+            return;
+        }
+
+        if (this._emptyMsgElement)
+            this._emptyMsgElement.parentElement.removeChild(this._emptyMsgElement);
+
+        this._refresh();
+        WebInspector.View.prototype.show.call(this, parentElement);
+    },
+
+    _refresh: function()
+    {
+        if (this._tableElement)
+            this._tableElement.parentElement.removeChild(this._tableElement);
+
+        this._tableElement = WebInspector.ResourceTimingView.createTimingTable(this._resource);
+        this.element.appendChild(this._tableElement);
+    }
+}
+
+WebInspector.ResourceTimingView.createTimingTable = function(resource)
+{
+    var tableElement = document.createElement("table");
+    var rows = [];
+
+    function addRow(title, className, start, end, color)
+    {
+        var row = {};
+        row.title = title;
+        row.className = className;
+        row.start = start;
+        row.end = end;
+        rows.push(row);
+    }
+
+    if (resource.timing.proxyStart !== -1)
+        addRow(WebInspector.UIString("Proxy"), "proxy", resource.timing.proxyStart, resource.timing.proxyEnd);
+
+    if (resource.timing.dnsStart !== -1)
+        addRow(WebInspector.UIString("DNS Lookup"), "dns", resource.timing.dnsStart, resource.timing.dnsEnd);
+
+    if (resource.timing.connectStart !== -1) {
+        if (resource.connectionReused)
+            addRow(WebInspector.UIString("Blocking"), "connecting", resource.timing.connectStart, resource.timing.connectEnd);
+        else {
+            var connectStart = resource.timing.connectStart;
+            // Connection includes DNS, subtract it here.
+            if (resource.timing.dnsStart !== -1)
+                connectStart += resource.timing.dnsEnd - resource.timing.dnsStart;
+            addRow(WebInspector.UIString("Connecting"), "connecting", connectStart, resource.timing.connectEnd);
+        }
+    }
+
+    if (resource.timing.sslStart !== -1)
+        addRow(WebInspector.UIString("SSL"), "ssl", resource.timing.sslStart, resource.timing.sslEnd);
+
+    var sendStart = resource.timing.sendStart;
+    if (resource.timing.sslStart !== -1)
+        sendStart += resource.timing.sslEnd - resource.timing.sslStart;
+    
+    addRow(WebInspector.UIString("Sending"), "sending", resource.timing.sendStart, resource.timing.sendEnd);
+    addRow(WebInspector.UIString("Waiting"), "waiting", resource.timing.sendEnd, resource.timing.receiveHeadersEnd);
+    addRow(WebInspector.UIString("Receiving"), "receiving", (resource.responseReceivedTime - resource.timing.requestTime) * 1000, (resource.endTime - resource.timing.requestTime) * 1000);
+
+    const chartWidth = 200;
+    var total = (resource.endTime - resource.timing.requestTime) * 1000;
+    var scale = chartWidth / total;
+
+    for (var i = 0; i < rows.length; ++i) {
+        var tr = document.createElement("tr");
+        tableElement.appendChild(tr);
+
+        var td = document.createElement("td");
+        td.textContent = rows[i].title;
+        tr.appendChild(td);
+
+        td = document.createElement("td");
+        td.width = chartWidth + "px";
+
+        var row = document.createElement("div");
+        row.className = "network-timing-row";
+        td.appendChild(row);
+
+        var bar = document.createElement("span");
+        bar.className = "network-timing-bar " + rows[i].className;
+        bar.style.left = scale * rows[i].start + "px";
+        bar.style.right = scale * (total - rows[i].end) + "px";
+        bar.style.backgroundColor = rows[i].color;
+        bar.textContent = "\u200B"; // Important for 0-time items to have 0 width.
+        row.appendChild(bar);
+
+        var title = document.createElement("span");
+        title.className = "network-timing-bar-title";
+        if (total - rows[i].end < rows[i].start)
+            title.style.right = (scale * (total - rows[i].end) + 3) + "px";
+        else
+            title.style.left = (scale * rows[i].start + 3) + "px";
+        title.textContent = Number.millisToString(rows[i].end - rows[i].start);
+        row.appendChild(title);
+
+        tr.appendChild(td);
+    }
+    return tableElement;
+}
+
+WebInspector.ResourceTimingView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTreeModel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTreeModel.js
new file mode 100644
index 0000000..da2d47a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceTreeModel.js
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+WebInspector.ResourceTreeModel = function()
+{
+    this.reset();
+}
+
+WebInspector.ResourceTreeModel.prototype = {
+    reset: function()
+    {
+        this._resourcesByURL = {};
+        this._resourcesByFrameId = {};
+        this._subframes = {};
+        if (WebInspector.panels)
+            WebInspector.panels.resources.clear();
+    },
+
+    addOrUpdateFrame: function(frame)
+    {
+        var tmpResource = new WebInspector.Resource(null, frame.url);
+        WebInspector.panels.resources.addOrUpdateFrame(frame.parentId, frame.id, frame.name, tmpResource.displayName);
+        var subframes = this._subframes[frame.parentId];
+        if (!subframes) {
+            subframes = {};
+            this._subframes[frame.parentId || 0] = subframes;
+        }
+        subframes[frame.id] = true;
+    },
+
+    didCommitLoadForFrame: function(frame, loader)
+    {
+        // frame.parentId === 0 is when main frame navigation happens.
+        this._clearChildFramesAndResources(frame.parentId ? frame.id : 0, loader.loaderId);
+
+        this.addOrUpdateFrame(frame);
+
+        var resourcesForFrame = this._resourcesByFrameId[frame.id];
+        for (var i = 0; resourcesForFrame && i < resourcesForFrame.length; ++i)
+            WebInspector.panels.resources.addResourceToFrame(frame.id, resourcesForFrame[i]);
+    },
+
+    frameDetachedFromParent: function(frameId)
+    {
+        this._clearChildFramesAndResources(frameId, 0);
+        WebInspector.panels.resources.removeFrame(frameId);
+    },
+
+    addResourceToFrame: function(frameId, resource)
+    {
+        var resourcesForFrame = this._resourcesByFrameId[frameId];
+        if (!resourcesForFrame) {
+            resourcesForFrame = [];
+            this._resourcesByFrameId[frameId] = resourcesForFrame;
+        }
+        resourcesForFrame.push(resource);
+        this._bindResourceURL(resource);
+
+        WebInspector.panels.resources.addResourceToFrame(frameId, resource);
+    },
+
+    forAllResources: function(callback)
+    {
+        this._callForFrameResources(0, callback);
+    },
+
+    addConsoleMessage: function(msg)
+    {
+        var resource = this.resourceForURL(msg.url);
+        if (!resource)
+            return;
+
+        switch (msg.level) {
+        case WebInspector.ConsoleMessage.MessageLevel.Warning:
+            resource.warnings += msg.repeatDelta;
+            break;
+        case WebInspector.ConsoleMessage.MessageLevel.Error:
+            resource.errors += msg.repeatDelta;
+            break;
+        }
+
+        var view = WebInspector.ResourceView.resourceViewForResource(resource);
+        if (view.addMessage)
+            view.addMessage(msg);
+    },
+
+    clearConsoleMessages: function()
+    {
+        function callback(resource)
+        {
+            resource.clearErrorsAndWarnings();
+        }
+        this.forAllResources(callback);
+    },
+
+    resourceForURL: function(url)
+    {
+        // FIXME: receive frameId here.
+        var entry = this._resourcesByURL[url];
+        if (entry instanceof Array)
+            return entry[0];
+        return entry;
+    },
+
+    _bindResourceURL: function(resource)
+    {
+        var resourceForURL = this._resourcesByURL[resource.url];
+        if (!resourceForURL)
+            this._resourcesByURL[resource.url] = resource;
+        else if (resourceForURL instanceof Array)
+            resourceForURL.push(resource);
+        else
+            this._resourcesByURL[resource.url] = [resourceForURL, resource];
+    },
+
+    _clearChildFramesAndResources: function(frameId, loaderId)
+    {
+        WebInspector.panels.resources.removeResourcesFromFrame(frameId);
+
+        this._clearResources(frameId, loaderId);
+        var subframes = this._subframes[frameId];
+        if (!subframes)
+            return;
+
+        for (var childFrameId in subframes) {
+            WebInspector.panels.resources.removeFrame(childFrameId);
+            this._clearChildFramesAndResources(childFrameId, loaderId);
+        }
+        delete this._subframes[frameId];
+    },
+
+    _clearResources: function(frameId, loaderToPreserveId)
+    {
+        var resourcesForFrame = this._resourcesByFrameId[frameId];
+        if (!resourcesForFrame)
+            return;
+
+        var preservedResourcesForFrame = [];
+        for (var i = 0; i < resourcesForFrame.length; ++i) {
+            var resource = resourcesForFrame[i];
+            if (resource.loader.loaderId === loaderToPreserveId) {
+                preservedResourcesForFrame.push(resource);
+                continue;
+            }
+            this._unbindResourceURL(resource);
+        }
+
+        delete this._resourcesByFrameId[frameId];
+        if (preservedResourcesForFrame.length)
+            this._resourcesByFrameId[frameId] = preservedResourcesForFrame;
+    },
+
+    _callForFrameResources: function(frameId, callback)
+    {
+        var resources = this._resourcesByFrameId[frameId];
+        for (var i = 0; resources && i < resources.length; ++i) {
+            if (callback(resources[i]))
+                return true;
+        }
+        
+        var frames = this._subframes[frameId];
+        if (frames) {
+            for (var id in frames) {
+                if (this._callForFrameResources(id, callback))
+                    return true;
+            }
+        }
+        return false;
+    },
+
+    _unbindResourceURL: function(resource)
+    {
+        var resourceForURL = this._resourcesByURL[resource.url];
+        if (!resourceForURL)
+            return;
+
+        if (resourceForURL instanceof Array) {
+            resourceForURL.remove(resource, true);
+            if (resourceForURL.length === 1)
+                this._resourcesByURL[resource.url] = resourceForURL[0];
+            return;
+        }
+
+        delete this._resourcesByURL[resource.url];
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceView.js
new file mode 100644
index 0000000..453a602
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourceView.js
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) IBM Corp. 2009  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceView = function(resource)
+{
+    WebInspector.View.call(this);
+    this.element.addStyleClass("resource-view");
+    this.resource = resource;
+}
+
+WebInspector.ResourceView.prototype = {
+    hasContent: function()
+    {
+        return false;
+    }
+}
+
+WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.ResourceView.createResourceView = function(resource)
+{
+    switch (resource.category) {
+    case WebInspector.resourceCategories.documents:
+    case WebInspector.resourceCategories.stylesheets:
+    case WebInspector.resourceCategories.scripts:
+    case WebInspector.resourceCategories.xhr:
+        var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
+        var isScript = resource.type === WebInspector.Resource.Type.Script;
+        var view = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
+        view.resource = resource;
+        return view;
+    case WebInspector.resourceCategories.images:
+        return new WebInspector.ImageView(resource);
+    case WebInspector.resourceCategories.fonts:
+        return new WebInspector.FontView(resource);
+    default:
+        return new WebInspector.ResourceView(resource);
+    }
+}
+
+WebInspector.ResourceView.resourceViewTypeMatchesResource = function(resource)
+{
+    var resourceView = resource._resourcesView;
+    switch (resource.category) {
+    case WebInspector.resourceCategories.documents:
+    case WebInspector.resourceCategories.stylesheets:
+    case WebInspector.resourceCategories.scripts:
+    case WebInspector.resourceCategories.xhr:
+        return resourceView.__proto__ === WebInspector.SourceFrame.prototype;
+    case WebInspector.resourceCategories.images:
+        return resourceView.__proto__ === WebInspector.ImageView.prototype;
+    case WebInspector.resourceCategories.fonts:
+        return resourceView.__proto__ === WebInspector.FontView.prototype;
+    default:
+        return resourceView.__proto__ === WebInspector.ResourceView.prototype;
+    }
+}
+
+WebInspector.ResourceView.resourceViewForResource = function(resource)
+{
+    if (!resource)
+        return null;
+    if (!resource._resourcesView)
+        resource._resourcesView = WebInspector.ResourceView.createResourceView(resource);
+    return resource._resourcesView;
+}
+
+WebInspector.ResourceView.recreateResourceView = function(resource)
+{
+    var newView = WebInspector.ResourceView.createResourceView(resource);
+
+    var oldView = resource._resourcesView;
+    var oldViewParentNode = oldView.visible ? oldView.element.parentNode : null;
+    var scrollTop = oldView.scrollTop;
+
+    resource._resourcesView.detach();
+    delete resource._resourcesView;
+
+    resource._resourcesView = newView;
+
+    if (oldViewParentNode)
+        newView.show(oldViewParentNode);
+    if (scrollTop)
+        newView.scrollTop = scrollTop;
+
+    return newView;
+}
+
+WebInspector.ResourceView.existingResourceViewForResource = function(resource)
+{
+    if (!resource)
+        return null;
+    return resource._resourcesView;
+}
+
+
+WebInspector.SourceFrameContentProviderForResource = function(resource)
+{
+    WebInspector.SourceFrameContentProvider.call(this);
+    this._resource = resource;
+}
+
+//This is a map from resource.type to mime types
+//found in WebInspector.SourceTokenizer.Registry.
+WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType = {
+    0: "text/html",
+    1: "text/css",
+    4: "text/javascript"
+}
+
+WebInspector.SourceFrameContentProviderForResource.prototype = {
+    requestContent: function(callback)
+    {
+        function contentLoaded(text)
+        {
+            var mimeType = WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType;
+            if (this._resource.type !== WebInspector.Resource.Type.Script) {
+                // WebKit html lexer normalizes line endings and scripts are passed to VM with "\n" line endings.
+                // However, resource content has original line endings, so we have to normalize line endings here.
+                text = text.replace(/\r\n/g, "\n");
+            }
+            var sourceMapping = new WebInspector.IdenticalSourceMapping();
+            var scripts = WebInspector.debuggerModel.scriptsForURL(this._resource.url);
+            var scriptRanges = WebInspector.ScriptFormatter.findScriptRanges(text.lineEndings(), scripts);
+            callback(mimeType, new WebInspector.SourceFrameContent(text, sourceMapping, scriptRanges));
+        }
+        this._resource.requestContent(contentLoaded.bind(this));
+    }
+}
+
+WebInspector.SourceFrameContentProviderForResource.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourcesPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourcesPanel.js
new file mode 100644
index 0000000..7c0649f
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ResourcesPanel.js
@@ -0,0 +1,1261 @@
+/*
+ * Copyright (C) 2007, 2008, 2010 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourcesPanel = function(database)
+{
+    WebInspector.Panel.call(this, "resources");
+
+    WebInspector.settings.installApplicationSetting("resourcesLastSelectedItem", {});
+
+    this.createSidebar();
+    this.sidebarElement.addStyleClass("outline-disclosure filter-all children small");
+    this.sidebarTreeElement.removeStyleClass("sidebar-tree");
+
+    this.resourcesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Frames"), "Frames", "frame-storage-tree-item");
+    this.sidebarTree.appendChild(this.resourcesListTreeElement);
+    this._treeElementForFrameId = {};
+
+    this.databasesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Databases"), "Databases", "database-storage-tree-item");
+    this.sidebarTree.appendChild(this.databasesListTreeElement);
+
+    this.localStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Local Storage"), "LocalStorage", "domstorage-storage-tree-item local-storage");
+    this.sidebarTree.appendChild(this.localStorageListTreeElement);
+
+    this.sessionStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Session Storage"), "SessionStorage", "domstorage-storage-tree-item session-storage");
+    this.sidebarTree.appendChild(this.sessionStorageListTreeElement);
+
+    this.cookieListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Cookies"), "Cookies", "cookie-storage-tree-item");
+    this.sidebarTree.appendChild(this.cookieListTreeElement);
+
+    this.applicationCacheListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Application Cache"), "ApplicationCache", "application-cache-storage-tree-item");
+    this.sidebarTree.appendChild(this.applicationCacheListTreeElement);
+
+    this.storageViews = document.createElement("div");
+    this.storageViews.id = "storage-views";
+    this.storageViews.className = "diff-container";
+    this.element.appendChild(this.storageViews);
+
+    this.storageViewStatusBarItemsContainer = document.createElement("div");
+    this.storageViewStatusBarItemsContainer.className = "status-bar-items";
+
+    this._databases = [];
+    this._domStorage = [];
+    this._cookieViews = {};
+    this._origins = {};
+    this._domains = {};
+
+    this.sidebarElement.addEventListener("mousemove", this._onmousemove.bind(this), false);
+    this.sidebarElement.addEventListener("mouseout", this._onmouseout.bind(this), false);
+
+    WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._refreshResource, this);
+}
+
+WebInspector.ResourcesPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Resources");
+    },
+
+    get statusBarItems()
+    {
+        return [this.storageViewStatusBarItemsContainer];
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [this.sidebarElement];
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+
+        if (this.visibleView && this.visibleView.resource)
+            this._showResourceView(this.visibleView.resource);
+
+        this._initDefaultSelection();
+    },
+
+    loadEventFired: function()
+    {
+        this._initDefaultSelection();
+    },
+
+    _initDefaultSelection: function()
+    {
+        if (this._initializedDefaultSelection)
+            return;
+
+        this._initializedDefaultSelection = true;
+        var itemURL = WebInspector.settings.resourcesLastSelectedItem;
+        if (itemURL) {
+            for (var treeElement = this.sidebarTree.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.sidebarTree, true)) {
+                if (treeElement.itemURL === itemURL) {
+                    treeElement.select();
+                    treeElement.reveal();
+                    return;
+                }
+            }
+        }
+
+        if (WebInspector.mainResource && this.resourcesListTreeElement && this.resourcesListTreeElement.expanded)
+            this.showResource(WebInspector.mainResource);
+    },
+
+    reset: function()
+    {
+        delete this._initializedDefaultSelection;
+        this._origins = {};
+        this._domains = {};
+        for (var i = 0; i < this._databases.length; ++i) {
+            var database = this._databases[i];
+            delete database._tableViews;
+            delete database._queryView;
+        }
+        this._databases = [];
+
+        var domStorageLength = this._domStorage.length;
+        for (var i = 0; i < this._domStorage.length; ++i) {
+            var domStorage = this._domStorage[i];
+            delete domStorage._domStorageView;
+        }
+        this._domStorage = [];
+
+        this._cookieViews = {};
+        
+        this._applicationCacheView = null;
+        delete this._cachedApplicationCacheViewStatus;
+
+        this.databasesListTreeElement.removeChildren();
+        this.localStorageListTreeElement.removeChildren();
+        this.sessionStorageListTreeElement.removeChildren();
+        this.cookieListTreeElement.removeChildren();
+        this.applicationCacheListTreeElement.removeChildren();
+        this.storageViews.removeChildren();
+
+        this.storageViewStatusBarItemsContainer.removeChildren();
+
+        if (this.sidebarTree.selectedTreeElement)
+            this.sidebarTree.selectedTreeElement.deselect();
+    },
+
+    clear: function()
+    {
+        this.resourcesListTreeElement.removeChildren();
+        this._treeElementForFrameId = {};
+        this.reset();
+    },
+
+    addOrUpdateFrame: function(parentFrameId, frameId, title, subtitle)
+    {
+        var frameTreeElement = this._treeElementForFrameId[frameId];
+        if (frameTreeElement) {
+            frameTreeElement.setTitles(title, subtitle);
+            return;
+        }
+
+        var parentTreeElement = parentFrameId ? this._treeElementForFrameId[parentFrameId] : this.resourcesListTreeElement;
+        if (!parentTreeElement) {
+            console.warning("No frame with id:" + parentFrameId + " to route " + displayName + " to.")
+            return;
+        }
+
+        var frameTreeElement = new WebInspector.FrameTreeElement(this, frameId, title, subtitle);
+        this._treeElementForFrameId[frameId] = frameTreeElement;
+
+        // Insert in the alphabetical order, first frames, then resources.
+        var children = parentTreeElement.children;
+        for (var i = 0; i < children.length; ++i) {
+            var child = children[i];
+            if (!(child instanceof WebInspector.FrameTreeElement)) {
+                parentTreeElement.insertChild(frameTreeElement, i);
+                return;
+            }
+            if (child.displayName.localeCompare(frameTreeElement.displayName) > 0) {
+                parentTreeElement.insertChild(frameTreeElement, i);
+                return;
+            }
+        }
+        parentTreeElement.appendChild(frameTreeElement);
+    },
+
+    removeFrame: function(frameId)
+    {
+        var frameTreeElement = this._treeElementForFrameId[frameId];
+        if (!frameTreeElement)
+            return;
+        delete this._treeElementForFrameId[frameId];
+        if (frameTreeElement.parent)
+            frameTreeElement.parent.removeChild(frameTreeElement);
+    },
+
+    addResourceToFrame: function(frameId, resource)
+    {
+        this.addDocumentURL(resource.documentURL);
+
+        if (resource.statusCode >= 301 && resource.statusCode <= 303)
+            return;
+
+        var frameTreeElement = this._treeElementForFrameId[frameId];
+        if (!frameTreeElement) {
+            // This is a frame's main resource, it will be retained
+            // and re-added by the resource manager;
+            return;
+        }
+
+        var resourceTreeElement = new WebInspector.FrameResourceTreeElement(this, resource);
+
+        // Insert in the alphabetical order, first frames, then resources. Document resource goes first.
+        var children = frameTreeElement.children;
+        for (var i = 0; i < children.length; ++i) {
+            var child = children[i];
+            if (!(child instanceof WebInspector.FrameResourceTreeElement))
+                continue;
+
+            if (resource.type === WebInspector.Resource.Type.Document ||
+                    (child._resource.type !== WebInspector.Resource.Type.Document && child._resource.displayName.localeCompare(resource.displayName) > 0)) {
+                frameTreeElement.insertChild(resourceTreeElement, i);
+                return;
+            }
+        }
+        frameTreeElement.appendChild(resourceTreeElement);
+    },
+
+    removeResourcesFromFrame: function(frameId)
+    {
+        var frameTreeElement = this._treeElementForFrameId[frameId];
+        if (frameTreeElement)
+            frameTreeElement.removeChildren();
+    },
+
+    _refreshResource: function(event)
+    {
+        var resource = event.data;
+        // FIXME: do not add XHR in the first place based on the native instrumentation.
+        if (resource.type === WebInspector.Resource.Type.XHR) {
+            var resourceTreeElement = this._findTreeElementForResource(resource);
+            if (resourceTreeElement)
+                resourceTreeElement.parent.removeChild(resourceTreeElement);
+        }
+    },
+
+    addDatabase: function(database)
+    {
+        this._databases.push(database);
+
+        var databaseTreeElement = new WebInspector.DatabaseTreeElement(this, database);
+        database._databasesTreeElement = databaseTreeElement;
+        this.databasesListTreeElement.appendChild(databaseTreeElement);
+    },
+
+    addDocumentURL: function(url)
+    {
+        var parsedURL = url.asParsedURL();
+        if (!parsedURL)
+            return;
+
+        var domain = parsedURL.host;
+        if (!this._domains[domain]) {
+            this._domains[domain] = true;
+
+            var cookieDomainTreeElement = new WebInspector.CookieTreeElement(this, domain);
+            this.cookieListTreeElement.appendChild(cookieDomainTreeElement);
+
+            var applicationCacheTreeElement = new WebInspector.ApplicationCacheTreeElement(this, domain);
+            this.applicationCacheListTreeElement.appendChild(applicationCacheTreeElement);
+        }
+    },
+
+    addDOMStorage: function(domStorage)
+    {
+        this._domStorage.push(domStorage);
+        var domStorageTreeElement = new WebInspector.DOMStorageTreeElement(this, domStorage, (domStorage.isLocalStorage ? "local-storage" : "session-storage"));
+        domStorage._domStorageTreeElement = domStorageTreeElement;
+        if (domStorage.isLocalStorage)
+            this.localStorageListTreeElement.appendChild(domStorageTreeElement);
+        else
+            this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
+    },
+
+    selectDatabase: function(databaseId)
+    {
+        var database;
+        for (var i = 0, len = this._databases.length; i < len; ++i) {
+            database = this._databases[i];
+            if (database.id === databaseId) {
+                this.showDatabase(database);
+                database._databasesTreeElement.select();
+                return;
+            }
+        }
+    },
+
+    selectDOMStorage: function(storageId)
+    {
+        var domStorage = this._domStorageForId(storageId);
+        if (domStorage) {
+            this.showDOMStorage(domStorage);
+            domStorage._domStorageTreeElement.select();
+        }
+    },
+
+    canShowSourceLine: function(url, line)
+    {
+        return !!WebInspector.resourceForURL(url);
+    },
+
+    showSourceLine: function(url, line)
+    {
+        var resource = WebInspector.resourceForURL(url);
+        if (resource.type === WebInspector.Resource.Type.XHR) {
+            // Show XHRs in the network panel only.
+            if (WebInspector.panels.network && WebInspector.panels.network.canShowSourceLine(url, line)) {
+                WebInspector.currentPanel = WebInspector.panels.network;
+                WebInspector.panels.network.showSourceLine(url, line);
+            }
+            return;
+        }
+        this.showResource(WebInspector.resourceForURL(url), line);
+    },
+
+    showResource: function(resource, line)
+    {
+        var resourceTreeElement = this._findTreeElementForResource(resource);
+        if (resourceTreeElement) {
+            resourceTreeElement.reveal();
+            resourceTreeElement.select();
+        }
+
+        if (line) {
+            var view = WebInspector.ResourceView.resourceViewForResource(resource);
+            if (view.revealLine)
+                view.revealLine(line);
+            if (view.highlightLine)
+                view.highlightLine(line);
+        }
+        return true;
+    },
+
+    _showResourceView: function(resource)
+    {
+        var view = WebInspector.ResourceView.resourceViewForResource(resource);
+
+        // Consider rendering diff markup here.
+        if (resource.baseRevision && view instanceof WebInspector.SourceFrame) {
+            function callback(baseContent)
+            {
+                if (baseContent)
+                    this._applyDiffMarkup(view, baseContent, resource.content);
+            }
+            resource.baseRevision.requestContent(callback.bind(this));
+        }
+        this._innerShowView(view);
+    },
+
+    _applyDiffMarkup: function(view, baseContent, newContent) {
+        var oldLines = baseContent.split("\n");
+        var newLines = newContent.split("\n");
+
+        var diff = Array.diff(oldLines, newLines);
+
+        var diffData = {};
+        diffData.added = [];
+        diffData.removed = [];
+        diffData.changed = [];
+
+        var offset = 0;
+        var right = diff.right;
+        for (var i = 0; i < right.length; ++i) {
+            if (typeof right[i] === "string") {
+                if (right.length > i + 1 && right[i + 1].row === i + 1 - offset)
+                    diffData.changed.push(i);
+                else {
+                    diffData.added.push(i);
+                    offset++;
+                }
+            } else
+                offset = i - right[i].row;
+        }
+        view.markDiff(diffData);
+    },
+
+    showDatabase: function(database, tableName)
+    {
+        if (!database)
+            return;
+            
+        var view;
+        if (tableName) {
+            if (!("_tableViews" in database))
+                database._tableViews = {};
+            view = database._tableViews[tableName];
+            if (!view) {
+                view = new WebInspector.DatabaseTableView(database, tableName);
+                database._tableViews[tableName] = view;
+            }
+        } else {
+            view = database._queryView;
+            if (!view) {
+                view = new WebInspector.DatabaseQueryView(database);
+                database._queryView = view;
+            }
+        }
+
+        this._innerShowView(view);
+    },
+
+    showDOMStorage: function(domStorage)
+    {
+        if (!domStorage)
+            return;
+
+        var view;
+        view = domStorage._domStorageView;
+        if (!view) {
+            view = new WebInspector.DOMStorageItemsView(domStorage);
+            domStorage._domStorageView = view;
+        }
+
+        this._innerShowView(view);
+    },
+
+    showCookies: function(treeElement, cookieDomain)
+    {
+        var view = this._cookieViews[cookieDomain];
+        if (!view) {
+            view = new WebInspector.CookieItemsView(treeElement, cookieDomain);
+            this._cookieViews[cookieDomain] = view;
+        }
+
+        this._innerShowView(view);
+    },
+
+    showApplicationCache: function(treeElement, appcacheDomain)
+    {
+        var view = this._applicationCacheView;
+        if (!view) {
+            view = new WebInspector.ApplicationCacheItemsView(treeElement, appcacheDomain);
+            this._applicationCacheView = view;
+        }
+
+        this._innerShowView(view);
+
+        if ("_cachedApplicationCacheViewStatus" in this)
+            this._applicationCacheView.updateStatus(this._cachedApplicationCacheViewStatus);
+    },
+
+    showCategoryView: function(categoryName)
+    {
+        if (!this._categoryView)
+            this._categoryView = new WebInspector.StorageCategoryView();
+        this._categoryView.setText(categoryName);
+        this._innerShowView(this._categoryView);
+    },
+
+    _innerShowView: function(view)
+    {
+        if (this.visibleView)
+            this.visibleView.hide();
+
+        view.show(this.storageViews);
+        this.visibleView = view;
+
+        this.storageViewStatusBarItemsContainer.removeChildren();
+        var statusBarItems = view.statusBarItems || [];
+        for (var i = 0; i < statusBarItems.length; ++i)
+            this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+    },
+
+    closeVisibleView: function()
+    {
+        if (this.visibleView)
+            this.visibleView.hide();
+        delete this.visibleView;
+    },
+
+    updateDatabaseTables: function(database)
+    {
+        if (!database || !database._databasesTreeElement)
+            return;
+
+        database._databasesTreeElement.shouldRefreshChildren = true;
+
+        if (!("_tableViews" in database))
+            return;
+
+        var tableNamesHash = {};
+        var self = this;
+        function tableNamesCallback(tableNames)
+        {
+            var tableNamesLength = tableNames.length;
+            for (var i = 0; i < tableNamesLength; ++i)
+                tableNamesHash[tableNames[i]] = true;
+
+            for (var tableName in database._tableViews) {
+                if (!(tableName in tableNamesHash)) {
+                    if (self.visibleView === database._tableViews[tableName])
+                        self.closeVisibleView();
+                    delete database._tableViews[tableName];
+                }
+            }
+        }
+        database.getTableNames(tableNamesCallback);
+    },
+
+    dataGridForResult: function(columnNames, values)
+    {
+        var numColumns = columnNames.length;
+        if (!numColumns)
+            return null;
+
+        var columns = {};
+
+        for (var i = 0; i < columnNames.length; ++i) {
+            var column = {};
+            column.width = columnNames[i].length;
+            column.title = columnNames[i];
+            column.sortable = true;
+
+            columns[columnNames[i]] = column;
+        }
+
+        var nodes = [];
+        for (var i = 0; i < values.length / numColumns; ++i) {
+            var data = {};
+            for (var j = 0; j < columnNames.length; ++j)
+                data[columnNames[j]] = values[numColumns * i + j];
+
+            var node = new WebInspector.DataGridNode(data, false);
+            node.selectable = false;
+            nodes.push(node);
+        }
+
+        var dataGrid = new WebInspector.DataGrid(columns);
+        var length = nodes.length;
+        for (var i = 0; i < length; ++i)
+            dataGrid.appendChild(nodes[i]);
+
+        dataGrid.addEventListener("sorting changed", this._sortDataGrid.bind(this, dataGrid), this);
+        return dataGrid;
+    },
+
+    _sortDataGrid: function(dataGrid)
+    {
+        var nodes = dataGrid.children.slice();
+        var sortColumnIdentifier = dataGrid.sortColumnIdentifier;
+        var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1;
+        var columnIsNumeric = true;
+
+        for (var i = 0; i < nodes.length; i++) {
+            if (isNaN(Number(nodes[i].data[sortColumnIdentifier])))
+                columnIsNumeric = false;
+        }
+
+        function comparator(dataGridNode1, dataGridNode2)
+        {
+            var item1 = dataGridNode1.data[sortColumnIdentifier];
+            var item2 = dataGridNode2.data[sortColumnIdentifier];
+
+            var comparison;
+            if (columnIsNumeric) {
+                // Sort numbers based on comparing their values rather than a lexicographical comparison.
+                var number1 = parseFloat(item1);
+                var number2 = parseFloat(item2);
+                comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0);
+            } else
+                comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0);
+
+            return sortDirection * comparison;
+        }
+
+        nodes.sort(comparator);
+        dataGrid.removeChildren();
+        for (var i = 0; i < nodes.length; i++)
+            dataGrid.appendChild(nodes[i]);
+    },
+
+    updateDOMStorage: function(storageId)
+    {
+        var domStorage = this._domStorageForId(storageId);
+        if (!domStorage)
+            return;
+
+        var view = domStorage._domStorageView;
+        if (this.visibleView && view === this.visibleView)
+            domStorage._domStorageView.update();
+    },
+
+    updateApplicationCacheStatus: function(status)
+    {
+        this._cachedApplicationCacheViewStatus = status;
+        if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
+            this._applicationCacheView.updateStatus(status);
+    },
+
+    updateNetworkState: function(isNowOnline)
+    {
+        if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
+            this._applicationCacheView.updateNetworkState(isNowOnline);
+    },
+
+    updateManifest: function(manifest)
+    {
+        if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
+            this._applicationCacheView.updateManifest(manifest);
+    },
+
+    _domStorageForId: function(storageId)
+    {
+        if (!this._domStorage)
+            return null;
+        var domStorageLength = this._domStorage.length;
+        for (var i = 0; i < domStorageLength; ++i) {
+            var domStorage = this._domStorage[i];
+            if (domStorage.id == storageId)
+                return domStorage;
+        }
+        return null;
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this.storageViews.style.left = width + "px";
+        this.storageViewStatusBarItemsContainer.style.left = width + "px";
+        this.resize();
+    },
+
+    get searchableViews()
+    {
+        var views = [];
+
+        const visibleView = this.visibleView;
+        if (visibleView.performSearch)
+            views.push(visibleView);
+
+        function callback(resourceTreeElement)
+        {
+            var resource = resourceTreeElement._resource;
+            var resourceView = WebInspector.ResourceView.resourceViewForResource(resource);
+            if (resourceView.performSearch && resourceView !== visibleView)
+                views.push(resourceView);
+        }
+        this._forAllResourceTreeElements(callback);
+        return views;
+    },
+
+    _forAllResourceTreeElements: function(callback)
+    {
+        var stop = false;
+        for (var treeElement = this.resourcesListTreeElement; !stop && treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.resourcesListTreeElement, true)) {
+            if (treeElement instanceof WebInspector.FrameResourceTreeElement)
+                stop = callback(treeElement);
+        }
+    },
+
+    searchMatchFound: function(view, matches)
+    {
+        if (!view.resource)
+            return;
+        var treeElement = this._findTreeElementForResource(view.resource);
+        if (treeElement)
+            treeElement.searchMatchFound(matches);
+    },
+
+    _findTreeElementForResource: function(resource)
+    {
+        function isAncestor(ancestor, object)
+        {
+            // Redirects, XHRs do not belong to the tree, it is fine to silently return false here.
+            return false;
+        }
+
+        function getParent(object)
+        {
+            // Redirects, XHRs do not belong to the tree, it is fine to silently return false here.
+            return null;
+        }
+
+        return this.sidebarTree.findTreeElement(resource, isAncestor, getParent);
+    },
+
+    searchCanceled: function(startingNewSearch)
+    {
+        WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+        if (startingNewSearch)
+            return;
+
+        function callback(resourceTreeElement)
+        {
+            resourceTreeElement._errorsWarningsUpdated();
+        }
+        this._forAllResourceTreeElements(callback);
+    },
+
+    performSearch: function(query)
+    {
+        function callback(resourceTreeElement)
+        {
+            resourceTreeElement._resetBubble();
+        }
+        this._forAllResourceTreeElements(callback);
+        WebInspector.Panel.prototype.performSearch.call(this, query);
+    },
+
+    showView: function(view)
+    {
+        if (view)
+            this.showResource(view.resource);
+    },
+
+    _onmousemove: function(event)
+    {
+        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+        if (!nodeUnderMouse)
+            return;
+
+        var listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName("li");
+        if (!listNode)
+            return;
+
+        var element = listNode.treeElement;
+        if (this._previousHoveredElement === element)
+            return;
+
+        if (this._previousHoveredElement) {
+            this._previousHoveredElement.hovered = false;
+            delete this._previousHoveredElement;
+        }
+
+        if (element instanceof WebInspector.FrameTreeElement) {
+            this._previousHoveredElement = element;
+            element.hovered = true;
+        }
+    },
+
+    _onmouseout: function(event)
+    {
+        if (this._previousHoveredElement) {
+            this._previousHoveredElement.hovered = false;
+            delete this._previousHoveredElement;
+        }
+    }
+}
+
+WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.BaseStorageTreeElement = function(storagePanel, representedObject, title, iconClass, hasChildren)
+{
+    TreeElement.call(this, "", representedObject, hasChildren);
+    this._storagePanel = storagePanel;
+    this._titleText = title;
+    this._iconClass = iconClass;
+}
+
+WebInspector.BaseStorageTreeElement.prototype = {
+    onattach: function()
+    {
+        this.listItemElement.removeChildren();
+        this.listItemElement.addStyleClass(this._iconClass);
+
+        var selectionElement = document.createElement("div");
+        selectionElement.className = "selection";
+        this.listItemElement.appendChild(selectionElement);
+
+        this.imageElement = document.createElement("img");
+        this.imageElement.className = "icon";
+        this.listItemElement.appendChild(this.imageElement);
+
+        this.titleElement = document.createElement("div");
+        this.titleElement.className = "base-storage-tree-element-title";
+        this.titleElement.textContent = this._titleText;
+        this.listItemElement.appendChild(this.titleElement);
+    },
+
+    onselect: function()
+    {
+        var itemURL = this.itemURL;
+        if (itemURL)
+            WebInspector.settings.resourcesLastSelectedItem = itemURL;
+    },
+
+    onreveal: function()
+    {
+        if (this.listItemElement)
+            this.listItemElement.scrollIntoViewIfNeeded(false);
+    },
+
+    get titleText()
+    {
+        return this._titleText;
+    },
+
+    set titleText(titleText)
+    {
+        this._titleText = titleText;
+        if (this.titleElement)
+            this.titleElement.textContent = this._titleText;
+    },
+
+    isEventWithinDisclosureTriangle: function()
+    {
+        // Override it since we use margin-left in place of treeoutline's text-indent.
+        // Hence we need to take padding into consideration. This all is needed for leading
+        // icons in the tree.
+        const paddingLeft = 14;
+        var left = this.listItemElement.totalOffsetLeft + paddingLeft;
+        return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
+    }
+}
+
+WebInspector.BaseStorageTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+WebInspector.StorageCategoryTreeElement = function(storagePanel, categoryName, settingsKey, iconClass)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, categoryName, iconClass, true);
+    this._expandedSettingKey = "resources" + settingsKey + "Expanded";
+    WebInspector.settings.installApplicationSetting(this._expandedSettingKey, settingsKey === "Frames");
+    this._categoryName = categoryName;
+}
+
+WebInspector.StorageCategoryTreeElement.prototype = {
+    get itemURL()
+    {
+        return "category://" + this._categoryName;
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showCategoryView(this._categoryName);
+    },
+
+    onattach: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
+        if (WebInspector.settings[this._expandedSettingKey])
+            this.expand();
+    },
+
+    onexpand: function()
+    {
+        WebInspector.settings[this._expandedSettingKey] = true;
+    },
+
+    oncollapse: function()
+    {
+        WebInspector.settings[this._expandedSettingKey] = false;
+    }
+}
+WebInspector.StorageCategoryTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.FrameTreeElement = function(storagePanel, frameId, title, subtitle)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", "frame-storage-tree-item");
+    this._frameId = frameId;
+    this.setTitles(title, subtitle);
+}
+
+WebInspector.FrameTreeElement.prototype = {
+    get itemURL()
+    {
+        return "frame://" + encodeURI(this._displayName);
+    },
+
+    onattach: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
+        if (this._titleToSetOnAttach || this._subtitleToSetOnAttach) {
+            this.setTitles(this._titleToSetOnAttach, this._subtitleToSetOnAttach);
+            delete this._titleToSetOnAttach;
+            delete this._subtitleToSetOnAttach;
+        }
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showCategoryView(this._displayName);
+
+        this.listItemElement.removeStyleClass("hovered");
+        InspectorBackend.hideFrameHighlight();
+    },
+
+    get displayName()
+    {
+        return this._displayName;
+    },
+
+    setTitles: function(title, subtitle)
+    {
+        this._displayName = "";
+        if (this.parent) {
+            if (title) {
+                this.titleElement.textContent = title;
+                this._displayName = title;
+            }
+            if (subtitle) {
+                var subtitleElement = document.createElement("span");
+                subtitleElement.className = "base-storage-tree-element-subtitle";
+                subtitleElement.textContent = "(" + subtitle + ")";
+                this._displayName += " (" + subtitle + ")";
+                this.titleElement.appendChild(subtitleElement);
+            }
+        } else {
+            this._titleToSetOnAttach = title;
+            this._subtitleToSetOnAttach = subtitle;
+        }
+    },
+
+    set hovered(hovered)
+    {
+        if (hovered) {
+            this.listItemElement.addStyleClass("hovered");
+            InspectorBackend.highlightFrame(this._frameId);
+        } else {
+            this.listItemElement.removeStyleClass("hovered");
+            InspectorBackend.hideFrameHighlight();
+        }
+    }
+}
+WebInspector.FrameTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.FrameResourceTreeElement = function(storagePanel, resource)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, resource, resource.displayName, "resource-sidebar-tree-item resources-category-" + resource.category.name);
+    this._resource = resource;
+    this._resource.addEventListener("errors-warnings-updated", this._errorsWarningsUpdated, this);
+    this._resource.addEventListener("content-changed", this._contentChanged, this);
+    this.tooltip = resource.url;
+}
+
+WebInspector.FrameResourceTreeElement.prototype = {
+    get itemURL()
+    {
+        return this._resource.url;
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel._showResourceView(this._resource);
+    },
+
+    ondblclick: function(event)
+    {
+        InspectorBackend.openInInspectedWindow(this._resource.url);
+    },
+
+    onattach: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
+
+        if (this._resource.category === WebInspector.resourceCategories.images) {
+            var previewImage = document.createElement("img");
+            previewImage.className = "image-resource-icon-preview";
+            this._resource.populateImageSource(previewImage);
+
+            var iconElement = document.createElement("div");
+            iconElement.className = "icon";
+            iconElement.appendChild(previewImage);
+            this.listItemElement.replaceChild(iconElement, this.imageElement);
+        }
+
+        this._statusElement = document.createElement("div");
+        this._statusElement.className = "status";
+        this.listItemElement.insertBefore(this._statusElement, this.titleElement);
+
+        this.listItemElement.draggable = true;
+        this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false);
+    },
+
+    _ondragstart: function(event)
+    {
+        event.dataTransfer.setData("text/plain", this._resource.content);
+        event.dataTransfer.effectAllowed = "copy";
+        return true;
+    },
+
+    _setBubbleText: function(x)
+    {
+        if (!this._bubbleElement) {
+            this._bubbleElement = document.createElement("div");
+            this._bubbleElement.className = "bubble";
+            this._statusElement.appendChild(this._bubbleElement);
+        }
+
+        this._bubbleElement.textContent = x;
+    },
+
+    _resetBubble: function()
+    {
+        if (this._bubbleElement) {
+            this._bubbleElement.textContent = "";
+            this._bubbleElement.removeStyleClass("search-matches");
+            this._bubbleElement.removeStyleClass("warning");
+            this._bubbleElement.removeStyleClass("error");
+        }
+    },
+
+    searchMatchFound: function(matches)
+    {
+        this._resetBubble();
+
+        this._setBubbleText(matches);
+        this._bubbleElement.addStyleClass("search-matches");
+
+        // Expand, do not scroll into view.
+        var currentAncestor = this.parent;
+        while (currentAncestor && !currentAncestor.root) {
+            if (!currentAncestor.expanded)
+                currentAncestor.expand();
+            currentAncestor = currentAncestor.parent;
+        }
+    },
+
+    _errorsWarningsUpdated: function()
+    {
+        // FIXME: move to the SourceFrame.
+        if (!this._resource.warnings && !this._resource.errors) {
+            var view = WebInspector.ResourceView.existingResourceViewForResource(this._resource);
+            if (view && view.clearMessages)
+                view.clearMessages();
+        }
+
+        if (this._storagePanel.currentQuery)
+            return;
+
+        this._resetBubble();
+
+        if (this._resource.warnings || this._resource.errors)
+            this._setBubbleText(this._resource.warnings + this._resource.errors);
+
+        if (this._resource.warnings)
+            this._bubbleElement.addStyleClass("warning");
+
+        if (this._resource.errors)
+            this._bubbleElement.addStyleClass("error");
+    },
+
+    _contentChanged: function(event)
+    {
+        this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, event.data.revision), 0);
+        var oldView = WebInspector.ResourceView.existingResourceViewForResource(this._resource);
+        if (oldView) {
+            var newView = WebInspector.ResourceView.recreateResourceView(this._resource);
+            if (oldView === this._storagePanel.visibleView)
+                this._storagePanel.visibleView = newView;
+        }
+    }
+}
+
+WebInspector.FrameResourceTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.DatabaseTreeElement = function(storagePanel, database)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, database.name, "database-storage-tree-item", true);
+    this._database = database;
+}
+
+WebInspector.DatabaseTreeElement.prototype = {
+    get itemURL()
+    {
+        return "database://" + encodeURI(this._database.name);
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showDatabase(this._database);
+    },
+
+    oncollapse: function()
+    {
+        // Request a refresh after every collapse so the next
+        // expand will have an updated table list.
+        this.shouldRefreshChildren = true;
+    },
+
+    onpopulate: function()
+    {
+        this.removeChildren();
+
+        function tableNamesCallback(tableNames)
+        {
+            var tableNamesLength = tableNames.length;
+            for (var i = 0; i < tableNamesLength; ++i)
+                this.appendChild(new WebInspector.DatabaseTableTreeElement(this._storagePanel, this._database, tableNames[i]));
+        }
+        this._database.getTableNames(tableNamesCallback.bind(this));
+    }
+
+}
+WebInspector.DatabaseTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.DatabaseTableTreeElement = function(storagePanel, database, tableName)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, tableName, "database-storage-tree-item");
+    this._database = database;
+    this._tableName = tableName;
+}
+
+WebInspector.DatabaseTableTreeElement.prototype = {
+    get itemURL()
+    {
+        return "database://" + encodeURI(this._database.name) + "/" + encodeURI(this._tableName);
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showDatabase(this._database, this._tableName);
+    }
+}
+WebInspector.DatabaseTableTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.DOMStorageTreeElement = function(storagePanel, domStorage, className)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, domStorage.domain ? domStorage.domain : WebInspector.UIString("Local Files"), "domstorage-storage-tree-item " + className);
+    this._domStorage = domStorage;
+}
+
+WebInspector.DOMStorageTreeElement.prototype = {
+    get itemURL()
+    {
+        return "storage://" + this._domStorage.domain + "/" + (this._domStorage.isLocalStorage ? "local" : "session");
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showDOMStorage(this._domStorage);
+    }
+}
+WebInspector.DOMStorageTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.CookieTreeElement = function(storagePanel, cookieDomain)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, cookieDomain ? cookieDomain : WebInspector.UIString("Local Files"), "cookie-storage-tree-item");
+    this._cookieDomain = cookieDomain;
+}
+
+WebInspector.CookieTreeElement.prototype = {
+    get itemURL()
+    {
+        return "cookies://" + this._cookieDomain;
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showCookies(this, this._cookieDomain);
+    }
+}
+WebInspector.CookieTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.ApplicationCacheTreeElement = function(storagePanel, appcacheDomain)
+{
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, appcacheDomain ? appcacheDomain : WebInspector.UIString("Local Files"), "application-cache-storage-tree-item");
+    this._appcacheDomain = appcacheDomain;
+}
+
+WebInspector.ApplicationCacheTreeElement.prototype = {
+    get itemURL()
+    {
+        return "appcache://" + this._appcacheDomain;
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel.showApplicationCache(this, this._appcacheDomain);
+    }
+}
+WebInspector.ApplicationCacheTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.ResourceRevisionTreeElement = function(storagePanel, revision)
+{
+    var title = revision.timestamp ? revision.timestamp.toLocaleTimeString() : WebInspector.UIString("(original)");
+    WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, title, "resource-sidebar-tree-item resources-category-" + revision.category.name);
+    if (revision.timestamp)
+        this.tooltip = revision.timestamp.toLocaleString();
+    this._resource = revision;
+}
+
+WebInspector.ResourceRevisionTreeElement.prototype = {
+    onattach: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
+        this.listItemElement.draggable = true;
+        this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false);
+        this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
+    },
+
+    onselect: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
+        this._storagePanel._showResourceView(this._resource);
+    },
+
+    _ondragstart: function(event)
+    {
+        event.dataTransfer.setData("text/plain", this._resource.content);
+        event.dataTransfer.effectAllowed = "copy";
+        return true;
+    },
+
+    _handleContextMenuEvent: function(event)
+    {
+        var contextMenu = new WebInspector.ContextMenu();
+        contextMenu.appendItem(WebInspector.UIString("Revert to this revision"), this._resource.revertToThis.bind(this._resource));
+        contextMenu.show(event);
+    }
+}
+
+WebInspector.ResourceRevisionTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;
+
+WebInspector.StorageCategoryView = function()
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("storage-view");
+
+    this._emptyMsgElement = document.createElement("div");
+    this._emptyMsgElement.className = "storage-empty-view";
+    this.element.appendChild(this._emptyMsgElement);
+}
+
+WebInspector.StorageCategoryView.prototype = {
+    setText: function(text)
+    {
+        this._emptyMsgElement.textContent = text;
+    }
+}
+
+WebInspector.StorageCategoryView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScopeChainSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScopeChainSidebarPane.js
new file mode 100644
index 0000000..bdbb0cf
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScopeChainSidebarPane.js
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScopeChainSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
+    this._sections = [];
+    this._expandedSections = {};
+    this._expandedProperties = [];
+}
+
+WebInspector.ScopeChainSidebarPane.prototype = {
+    update: function(callFrame)
+    {
+        this.bodyElement.removeChildren();
+
+        if (!callFrame) {
+            var infoElement = document.createElement("div");
+            infoElement.className = "info";
+            infoElement.textContent = WebInspector.UIString("Not Paused");
+            this.bodyElement.appendChild(infoElement);
+            return;
+        }
+
+        for (var i = 0; i < this._sections.length; ++i) {
+            var section = this._sections[i];
+            if (!section.title)
+                continue;
+            if (section.expanded)
+                this._expandedSections[section.title] = true;
+            else
+                delete this._expandedSections[section.title];
+        }
+
+        this._sections = [];
+
+        var foundLocalScope = false;
+        var scopeChain = callFrame.scopeChain;
+        for (var i = 0; i < scopeChain.length; ++i) {
+            var scopeObjectProxy = scopeChain[i];
+            var title = null;
+            var subtitle = scopeObjectProxy.description;
+            var emptyPlaceholder = null;
+            var extraProperties = null;
+
+            if (scopeObjectProxy.isLocal) {
+                foundLocalScope = true;
+                title = WebInspector.UIString("Local");
+                emptyPlaceholder = WebInspector.UIString("No Variables");
+                subtitle = null;
+                if (scopeObjectProxy.thisObject)
+                    extraProperties = [ new WebInspector.RemoteObjectProperty("this", WebInspector.RemoteObject.fromPayload(scopeObjectProxy.thisObject)) ];
+            } else if (scopeObjectProxy.isClosure) {
+                title = WebInspector.UIString("Closure");
+                emptyPlaceholder = WebInspector.UIString("No Variables");
+                subtitle = null;
+            } else if (i === (scopeChain.length - 1))
+                title = WebInspector.UIString("Global");
+            else if (scopeObjectProxy.isElement)
+                title = WebInspector.UIString("Event Target");
+            else if (scopeObjectProxy.isDocument)
+                title = WebInspector.UIString("Event Document");
+            else if (scopeObjectProxy.isWithBlock)
+                title = WebInspector.UIString("With Block");
+
+            if (!title || title === subtitle)
+                subtitle = null;
+
+            var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scopeObjectProxy), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+            section.editInSelectedCallFrameWhenPaused = true;
+            section.pane = this;
+
+            if (!foundLocalScope || scopeObjectProxy.isLocal || title in this._expandedSections)
+                section.expanded = true;
+
+            this._sections.push(section);
+            this.bodyElement.appendChild(section.element);
+        }
+    }
+}
+
+WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.ScopeVariableTreeElement = function(property)
+{
+    WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.ScopeVariableTreeElement.prototype = {
+    onattach: function()
+    {
+        WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+        if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties)
+            this.expand();
+    },
+
+    onexpand: function()
+    {
+        this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true;
+    },
+
+    oncollapse: function()
+    {
+        delete this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier];
+    },
+
+    get propertyIdentifier()
+    {
+        if ("_propertyIdentifier" in this)
+            return this._propertyIdentifier;
+        var section = this.treeOutline.section;
+        this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath;
+        return this._propertyIdentifier;
+    },
+
+    get propertyPath()
+    {
+        if ("_propertyPath" in this)
+            return this._propertyPath;
+
+        var current = this;
+        var result;
+
+        do {
+            if (result)
+                result = current.property.name + "." + result;
+            else
+                result = current.property.name;
+            current = current.parent;
+        } while (current && !current.root);
+
+        this._propertyPath = result;
+        return result;
+    }
+}
+
+WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Script.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Script.js
new file mode 100644
index 0000000..8d3eabf
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Script.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Script = function(sourceID, sourceURL, source, lineOffset, columnOffset, length, errorLine, errorMessage, worldType)
+{
+    this.sourceID = sourceID;
+    this.sourceURL = sourceURL;
+    this._source = source;
+    this.lineOffset = lineOffset;
+    this.columnOffset = columnOffset;
+    this.length = length;
+    this.errorLine = errorLine;
+    this.errorMessage = errorMessage;
+    this.worldType = worldType;
+
+    // if no URL, look for "//@ sourceURL=" decorator
+    // note that this sourceURL comment decorator is behavior that FireBug added
+    // in it's 1.1 release as noted in the release notes:
+    // http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
+    if (!sourceURL) {
+        // use of [ \t] rather than \s is to prevent \n from matching
+        var pattern = /^\s*\/\/[ \t]*@[ \t]*sourceURL[ \t]*=[ \t]*(\S+).*$/m;
+        var match = pattern.exec(source);
+
+        if (match)
+            this.sourceURL = match[1];
+    }
+}
+
+WebInspector.Script.WorldType = {
+    MAIN_WORLD: 0,
+    EXTENSIONS_WORLD: 1
+}
+
+WebInspector.Script.WorldType = {
+    MAIN_WORLD: 0,
+    EXTENSIONS_WORLD: 1
+}
+
+WebInspector.Script.prototype = {
+    get startingLine()
+    {
+        return this.lineOffset + 1;
+    },
+
+    get linesCount()
+    {
+        if (!this.source)
+            return 0;
+        if (!this._lineEndings)
+            this._lineEndings = this._source.findAll("\n");
+        return this._lineEndings.length + 1;
+    },
+
+    sourceLine: function(lineNumber, callback)
+    {
+        function extractSourceLine()
+        {
+            lineNumber -= this.lineOffset;
+            callback(this._source.substring(this._lineEndings[lineNumber - 1], this._lineEndings[lineNumber]));
+        }
+
+        if (this._lineEndings) {
+            extractSourceLine.call(this);
+            return;
+        }
+
+        function didRequestSource()
+        {
+            this._lineEndings = this._source.findAll("\n");
+            extractSourceLine.call(this);
+        }
+        this.requestSource(didRequestSource.bind(this));
+    },
+
+    get source()
+    {
+        if (!this._source && this.resource)
+            this._source = this.resource.content;
+        return this._source;
+    },
+
+    set source(source)
+    {
+        this._source = source;
+        delete this._lineEndings;
+    },
+
+    requestSource: function(callback)
+    {
+        if (this._source) {
+            callback(this._source);
+            return;
+        }
+
+        function didGetScriptSource(source)
+        {
+            this._source = source;
+            callback(this._source);
+        }
+        InspectorBackend.getScriptSource(this.sourceID, didGetScriptSource.bind(this));
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatter.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatter.js
new file mode 100644
index 0000000..f70d6c6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatter.js
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptFormatter = function()
+{
+    this._worker = new Worker("ScriptFormatterWorker.js");
+    this._worker.onmessage = this._handleMessage.bind(this);
+    this._worker.onerror = this._handleError.bind(this);
+    this._tasks = [];
+}
+
+WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
+{
+    var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
+    return position + columnNumber;
+}
+
+WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position)
+{
+    var location = {};
+    location.lineNumber = lineEndings.upperBound(position - 1);
+    if (!location.lineNumber)
+        location.columnNumber = position;
+    else
+        location.columnNumber = position - lineEndings[location.lineNumber - 1] - 1;
+    return location;
+}
+
+WebInspector.ScriptFormatter.findScriptRanges = function(lineEndings, scripts)
+{
+    var scriptRanges = [];
+    for (var i = 0; i < scripts.length; ++i) {
+        var start = { lineNumber: scripts[i].lineOffset, columnNumber: scripts[i].columnOffset };
+        start.position = WebInspector.ScriptFormatter.locationToPosition(lineEndings, start.lineNumber, start.columnNumber);
+        var endPosition = start.position + scripts[i].length;
+        var end = WebInspector.ScriptFormatter.positionToLocation(lineEndings, endPosition);
+        end.position = endPosition;
+        scriptRanges.push({ start: start, end: end, sourceID: scripts[i].sourceID });
+    }
+    scriptRanges.sort(function(x, y) { return x.start.position - y.start.position; });
+    return scriptRanges;
+}
+
+WebInspector.ScriptFormatter.prototype = {
+    formatContent: function(content, callback)
+    {
+        var chunks = this._splitContentIntoChunks(content.text, content.scriptRanges);
+
+        function didFormatChunks()
+        {
+            var result = this._buildContentFromChunks(chunks);
+
+            var sourceMapping = new WebInspector.SourceMappingForFormattedScript(content.text.lineEndings(), result.text.lineEndings(), result.mapping);
+            var formattedScriptRanges = [];
+            for (var i = 0; i < content.scriptRanges.length; ++i) {
+                var scriptRange = content.scriptRanges[i];
+                formattedScriptRange = {};
+                formattedScriptRange.start = sourceMapping.originalPositionToFormattedLocation(scriptRange.start.position);
+                formattedScriptRange.end = sourceMapping.originalPositionToFormattedLocation(scriptRange.end.position);
+                formattedScriptRange.sourceID = scriptRange.sourceID;
+                formattedScriptRanges.push(formattedScriptRange);
+            }
+            callback(new WebInspector.SourceFrameContent(result.text, sourceMapping, formattedScriptRanges));
+        }
+        this._formatChunks(chunks, 0, didFormatChunks.bind(this));
+    },
+
+    _splitContentIntoChunks: function(text, scriptRanges)
+    {
+        var chunks = [];
+        function addChunk(start, end, isScript)
+        {
+            var chunk = {};
+            chunk.start = start;
+            chunk.end = end;
+            chunk.isScript = isScript;
+            chunk.text = text.substring(start, end);
+            chunks.push(chunk);
+        }
+        var currentPosition = 0;
+        for (var i = 0; i < scriptRanges.length; ++i) {
+            var start = scriptRanges[i].start.position;
+            var end = scriptRanges[i].end.position;
+            if (currentPosition < start)
+                addChunk(currentPosition, start, false);
+            addChunk(start, end, true);
+            currentPosition = end;
+        }
+        if (currentPosition < text.length)
+            addChunk(currentPosition, text.length, false);
+        return chunks;
+    },
+
+    _formatChunks: function(chunks, index, callback)
+    {
+        while(true) {
+            if (index === chunks.length) {
+                callback();
+                return;
+            }
+            var chunk = chunks[index++];
+            if (chunk.isScript)
+                break;
+        }
+
+        function didFormat(formattedSource, mapping)
+        {
+            chunk.text = formattedSource;
+            chunk.mapping = mapping;
+            this._formatChunks(chunks, index, callback);
+        }
+        this._formatScript(chunk.text, didFormat.bind(this));
+    },
+
+    _buildContentFromChunks: function(chunks)
+    {
+        var text = "";
+        var mapping = { original: [], formatted: [] };
+        for (var i = 0; i < chunks.length; ++i) {
+            var chunk = chunks[i];
+            mapping.original.push(chunk.start);
+            mapping.formatted.push(text.length);
+            if (chunk.isScript) {
+                if (text)
+                    text += "\n";
+                for (var j = 0; j < chunk.mapping.original.length; ++j) {
+                    mapping.original.push(chunk.mapping.original[j] + chunk.start);
+                    mapping.formatted.push(chunk.mapping.formatted[j] + text.length);
+                }
+                text += chunk.text;
+            } else {
+                if (text)
+                    text += "\n";
+                text += chunk.text;
+            }
+            mapping.original.push(chunk.end);
+            mapping.formatted.push(text.length);
+        }
+        return { text: text, mapping: mapping };
+    },
+
+    _formatScript: function(source, callback)
+    {
+        this._tasks.push({ source: source, callback: callback });
+        this._worker.postMessage(source);
+    },
+
+    _handleMessage: function(event)
+    {
+        var task = this._tasks.shift();
+        task.callback(event.data.formattedSource, event.data.mapping);
+    },
+
+    _handleError: function(event)
+    {
+        console.warn("Error in script formatter worker:", event);
+        event.preventDefault()
+        var task = this._tasks.shift();
+        task.callback(task.source, { original: [], formatted: [] });
+    }
+}
+
+
+WebInspector.SourceMappingForFormattedScript = function(originalLineEndings, formattedLineEndings, mapping)
+{
+    WebInspector.SourceMapping.call(this);
+    this._originalLineEndings = originalLineEndings;
+    this._formattedLineEndings = formattedLineEndings;
+    this._mapping = mapping;
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype = {
+    actualLocationToSourceLocation: function(lineNumber, columnNumber)
+    {
+        var position = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber);
+        return this.originalPositionToFormattedLocation(position);
+    },
+
+    sourceLocationToActualLocation: function(lineNumber, columnNumber)
+    {
+        var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber);
+        var position = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
+        return WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, position);
+    },
+
+    originalPositionToFormattedLocation: function(position)
+    {
+        var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, position);
+        var location = WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition);
+        location.position = formattedPosition;
+        return location;
+    },
+
+    _convertPosition: function(positions1, positions2, position)
+    {
+        var index = positions1.upperBound(position);
+        var range1 = positions1[index] - positions1[index - 1];
+        var range2 = positions2[index] - positions2[index - 1];
+        var position2 = positions2[index - 1];
+        if (range1)
+            position2 += Math.round((position - positions1[index - 1]) * range2 / range1);
+        return position2;
+    }
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatterWorker.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatterWorker.js
new file mode 100644
index 0000000..1a4c28e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptFormatterWorker.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var parse = loadModule("parse-js.js");
+var process = loadModule("process.js");
+
+onmessage = function(event) {
+    var source = event.data;
+    var formattedSource = beautify(source);
+    var mapping = buildMapping(source, formattedSource);
+    postMessage({ formattedSource: formattedSource, mapping: mapping });
+};
+
+function beautify(source)
+{
+    var ast = parse.parse(source);
+    var beautifyOptions = {
+        indent_level: 4,
+        indent_start: 0,
+        quote_keys: false,
+        space_colon: false
+    };
+    return process.gen_code(ast, beautifyOptions);
+}
+
+function buildMapping(source, formattedSource)
+{
+    var mapping = { original: [], formatted: [] };
+    var lastCodePosition = 0;
+    var regexp = /[\$\.\w]+|{|}/g;
+    while (true) {
+        var match = regexp.exec(formattedSource);
+        if (!match)
+            break;
+        var position = source.indexOf(match[0], lastCodePosition);
+        if (position === -1)
+            continue;
+        mapping.original.push(position);
+        mapping.formatted.push(match.index);
+        lastCodePosition = position + match[0].length;
+    }
+    return mapping;
+}
+
+function loadModule(src)
+{
+    var request = new XMLHttpRequest();
+    request.open("GET", src, false);
+    request.send();
+
+    var exports = {};
+    eval(request.responseText);
+    return exports;
+}
+
+function require()
+{
+    return parse;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptsPanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptsPanel.js
new file mode 100644
index 0000000..3b24d45
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ScriptsPanel.js
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptsPanel = function()
+{
+    WebInspector.Panel.call(this, "scripts");
+
+    this.topStatusBar = document.createElement("div");
+    this.topStatusBar.className = "status-bar";
+    this.topStatusBar.id = "scripts-status-bar";
+    this.element.appendChild(this.topStatusBar);
+
+    this.backButton = document.createElement("button");
+    this.backButton.className = "status-bar-item";
+    this.backButton.id = "scripts-back";
+    this.backButton.title = WebInspector.UIString("Show the previous script resource.");
+    this.backButton.disabled = true;
+    this.backButton.appendChild(document.createElement("img"));
+    this.backButton.addEventListener("click", this._goBack.bind(this), false);
+    this.topStatusBar.appendChild(this.backButton);
+
+    this.forwardButton = document.createElement("button");
+    this.forwardButton.className = "status-bar-item";
+    this.forwardButton.id = "scripts-forward";
+    this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
+    this.forwardButton.disabled = true;
+    this.forwardButton.appendChild(document.createElement("img"));
+    this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
+    this.topStatusBar.appendChild(this.forwardButton);
+
+    this.filesSelectElement = document.createElement("select");
+    this.filesSelectElement.className = "status-bar-item";
+    this.filesSelectElement.id = "scripts-files";
+    this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
+    this.topStatusBar.appendChild(this.filesSelectElement);
+
+    this.functionsSelectElement = document.createElement("select");
+    this.functionsSelectElement.className = "status-bar-item";
+    this.functionsSelectElement.id = "scripts-functions";
+
+    // FIXME: append the functions select element to the top status bar when it is implemented.
+    // this.topStatusBar.appendChild(this.functionsSelectElement);
+
+    this.formatButton = document.createElement("button");
+    this.formatButton.className = "status-bar-item";
+    this.formatButton.id = "format-script";
+    this.formatButton.title = WebInspector.UIString("Format script.");
+    this.formatButton.appendChild(document.createElement("img"));
+    this.formatButton.addEventListener("click", this._formatScript.bind(this), false);
+    if (Preferences.debugMode)
+        this.topStatusBar.appendChild(this.formatButton);
+
+    this.sidebarButtonsElement = document.createElement("div");
+    this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
+    this.topStatusBar.appendChild(this.sidebarButtonsElement);
+
+    this.pauseButton = document.createElement("button");
+    this.pauseButton.className = "status-bar-item";
+    this.pauseButton.id = "scripts-pause";
+    this.pauseButton.title = WebInspector.UIString("Pause script execution.");
+    this.pauseButton.disabled = true;
+    this.pauseButton.appendChild(document.createElement("img"));
+    this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
+    this.sidebarButtonsElement.appendChild(this.pauseButton);
+
+    this.stepOverButton = document.createElement("button");
+    this.stepOverButton.className = "status-bar-item";
+    this.stepOverButton.id = "scripts-step-over";
+    this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
+    this.stepOverButton.disabled = true;
+    this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
+    this.stepOverButton.appendChild(document.createElement("img"));
+    this.sidebarButtonsElement.appendChild(this.stepOverButton);
+
+    this.stepIntoButton = document.createElement("button");
+    this.stepIntoButton.className = "status-bar-item";
+    this.stepIntoButton.id = "scripts-step-into";
+    this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
+    this.stepIntoButton.disabled = true;
+    this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
+    this.stepIntoButton.appendChild(document.createElement("img"));
+    this.sidebarButtonsElement.appendChild(this.stepIntoButton);
+
+    this.stepOutButton = document.createElement("button");
+    this.stepOutButton.className = "status-bar-item";
+    this.stepOutButton.id = "scripts-step-out";
+    this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
+    this.stepOutButton.disabled = true;
+    this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
+    this.stepOutButton.appendChild(document.createElement("img"));
+    this.sidebarButtonsElement.appendChild(this.stepOutButton);
+
+    this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
+    this.toggleBreakpointsButton.toggled = true;
+    this.toggleBreakpointsButton.addEventListener("click", this.toggleBreakpointsClicked.bind(this), false);
+    this.sidebarButtonsElement.appendChild(this.toggleBreakpointsButton.element);
+
+    this.debuggerStatusElement = document.createElement("div");
+    this.debuggerStatusElement.id = "scripts-debugger-status";
+    this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
+
+    this.viewsContainerElement = document.createElement("div");
+    this.viewsContainerElement.id = "script-resource-views";
+
+    this.sidebarElement = document.createElement("div");
+    this.sidebarElement.id = "scripts-sidebar";
+
+    this.sidebarResizeElement = document.createElement("div");
+    this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+    this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+
+    this.sidebarResizeWidgetElement = document.createElement("div");
+    this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
+    this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+    this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
+
+    this.sidebarPanes = {};
+    this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
+    this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+    this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
+    this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane();
+    if (Preferences.nativeInstrumentationEnabled) {
+        this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane();
+        this.sidebarPanes.xhrBreakpoints = WebInspector.createXHRBreakpointsSidebarPane();
+        this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
+    }
+
+    this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
+
+    for (var pane in this.sidebarPanes)
+        this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
+
+    this.sidebarPanes.callstack.expanded = true;
+    this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
+
+    this.sidebarPanes.scopechain.expanded = true;
+    this.sidebarPanes.jsBreakpoints.expanded = true;
+
+    var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
+    var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
+    var panelEnablerButton = WebInspector.UIString("Enable Debugging");
+
+    this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+    this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
+
+    this.element.appendChild(this.panelEnablerView.element);
+    this.element.appendChild(this.viewsContainerElement);
+    this.element.appendChild(this.sidebarElement);
+    this.element.appendChild(this.sidebarResizeElement);
+
+    this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
+    this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
+    if (Preferences.debuggerAlwaysEnabled)
+        this.enableToggleButton.element.addStyleClass("hidden");
+
+    this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
+    this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
+
+    this._registerShortcuts();
+
+    this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;
+
+    this.reset();
+
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._failedToParseScriptSource, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ScriptSourceChanged, this._scriptSourceChanged, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
+    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+}
+
+// Keep these in sync with WebCore::ScriptDebugServer
+WebInspector.ScriptsPanel.PauseOnExceptionsState = {
+    DontPauseOnExceptions : 0,
+    PauseOnAllExceptions : 1,
+    PauseOnUncaughtExceptions: 2
+};
+
+WebInspector.ScriptsPanel.prototype = {
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Scripts");
+    },
+
+    get statusBarItems()
+    {
+        return [this.enableToggleButton.element, this._pauseOnExceptionButton.element];
+    },
+
+    get defaultFocusedElement()
+    {
+        return this.filesSelectElement;
+    },
+
+    get paused()
+    {
+        return this._paused;
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+
+        if (this.visibleView)
+            this.visibleView.show(this.viewsContainerElement);
+    },
+
+    hide: function()
+    {
+        if (this.visibleView)
+            this.visibleView.hide();
+        WebInspector.Panel.prototype.hide.call(this);
+    },
+
+    get breakpointsActivated()
+    {
+        return this.toggleBreakpointsButton.toggled;
+    },
+
+    _parsedScriptSource: function(event)
+    {
+        this._addScript(event.data);
+    },
+
+    _failedToParseScriptSource: function(event)
+    {
+        this._addScript(event.data);
+    },
+
+    _scriptSourceChanged: function(event)
+    {
+        var sourceID = event.data.sourceID;
+        var oldSource = event.data.oldSource;
+
+        var oldView, newView;
+        var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
+        if (script.resource) {
+            oldView = this._urlToSourceFrame[script.resource.url];
+            delete this._urlToSourceFrame[script.resource.url];
+            newView = this._sourceFrameForResource(script.resource);
+            var revertHandle = WebInspector.debuggerModel.editScriptSource.bind(WebInspector.debuggerModel, sourceID, oldSource);
+            script.resource.setContent(script.source, revertHandle);
+        } else {
+            var oldView = script._sourceFrame;
+            delete script._sourceFrame;
+            newView = this._sourceFrameForScript(script);
+        }
+        newView.scrollTop = oldView.scrollTop;
+
+        if (this.visibleView === oldView)
+            this.visibleView = newView;
+
+        var callFrames = WebInspector.debuggerModel.callFrames;
+        if (callFrames.length)
+            this._debuggerPaused({ data: { callFrames: callFrames } });
+    },
+
+    _addScript: function(script)
+    {
+        var resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
+        if (resource) {
+            if (resource.finished) {
+                // Resource is finished, bind the script right away.
+                script.resource = resource;
+            } else {
+                // Resource is not finished, bind the script later.
+                if (!resource._scriptsPendingResourceLoad) {
+                    resource._scriptsPendingResourceLoad = [];
+                    resource.addEventListener("finished", this._resourceLoadingFinished, this);
+                }
+                resource._scriptsPendingResourceLoad.push(script);
+            }
+        }
+        this._addScriptToFilesMenu(script);
+    },
+
+    _resourceLoadingFinished: function(e)
+    {
+        var resource = e.target;
+
+        var visible = false;
+        var select = this.filesSelectElement;
+        for (var i = 0; i < resource._scriptsPendingResourceLoad.length; ++i) {
+            // Bind script to resource.
+            var script = resource._scriptsPendingResourceLoad[i];
+            script.resource = resource;
+
+            if (select.options[select.selectedIndex] === script.filesSelectOption)
+                visible = true;
+
+            // Remove script from the files list.
+            script.filesSelectOption.parentElement.removeChild(script.filesSelectOption);
+        }
+        // Adding first script will add resource.
+        this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
+        delete resource._scriptsPendingResourceLoad;
+
+        if (visible)
+            this._showScriptOrResource(resource, { initialLoad: true });
+    },
+
+    addConsoleMessage: function(message)
+    {
+        this._messages.push(message);
+        var sourceFrame = this._urlToSourceFrame[message.url];
+        if (sourceFrame)
+            sourceFrame.addMessage(message);
+    },
+
+    clearConsoleMessages: function()
+    {
+        this._messages = [];
+        for (var url in this._urlToSourceFrame)
+            this._urlToSourceFrame[url].clearMessages();
+    },
+
+    selectedCallFrameId: function()
+    {
+        var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+        if (!selectedCallFrame)
+            return null;
+        return selectedCallFrame.id;
+    },
+
+    evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, includeCommandLineAPI, callback)
+    {
+        var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+        if (!this._paused || !selectedCallFrame)
+            return;
+
+        if (typeof updateInterface === "undefined")
+            updateInterface = true;
+
+        function updatingCallbackWrapper(result)
+        {
+            if (result) {
+                callback(WebInspector.RemoteObject.fromPayload(result));
+                if (updateInterface)
+                    this.sidebarPanes.scopechain.update(selectedCallFrame);
+            }
+        }
+        InspectorBackend.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
+    },
+
+    _debuggerPaused: function(event)
+    {
+        var callFrames = event.data.callFrames;
+
+        this._paused = true;
+        this._waitingToPause = false;
+        this._stepping = false;
+
+        this._updateDebuggerButtons();
+
+        WebInspector.currentPanel = this;
+
+        this.sidebarPanes.callstack.update(event.data);
+        this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
+
+        window.focus();
+        InspectorFrontendHost.bringToFront();
+    },
+
+    _debuggerResumed: function()
+    {
+        this._paused = false;
+        this._waitingToPause = false;
+        this._stepping = false;
+
+        this._clearInterface();
+    },
+
+    debuggerWasEnabled: function()
+    {
+        this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionState);
+
+        if (this._debuggerEnabled)
+            return;
+        this._debuggerEnabled = true;
+        this.reset(true);
+    },
+
+    debuggerWasDisabled: function()
+    {
+        if (!this._debuggerEnabled)
+            return;
+
+        this._debuggerEnabled = false;
+        this.reset(true);
+    },
+
+    reset: function(preserveItems)
+    {
+        this.visibleView = null;
+
+        delete this.currentQuery;
+        this.searchCanceled();
+
+        this._debuggerResumed();
+
+        this._backForwardList = [];
+        this._currentBackForwardIndex = -1;
+        this._updateBackAndForwardButtons();
+
+        this._urlToSourceFrame = {};
+        this._messages = [];
+        this._resourceForURLInFilesSelect = {};
+        this.filesSelectElement.removeChildren();
+        this.functionsSelectElement.removeChildren();
+        this.viewsContainerElement.removeChildren();
+
+        this.sidebarPanes.watchExpressions.refreshExpressions();
+        if (!preserveItems)
+            this.sidebarPanes.workers.reset();
+    },
+
+    get visibleView()
+    {
+        return this._visibleView;
+    },
+
+    set visibleView(x)
+    {
+        if (this._visibleView === x)
+            return;
+
+        if (this._visibleView)
+            this._visibleView.hide();
+
+        this._visibleView = x;
+
+        if (x)
+            x.show(this.viewsContainerElement);
+    },
+
+    canShowSourceLine: function(url, line)
+    {
+        if (!this._debuggerEnabled)
+            return false;
+        return !!this._scriptOrResourceForURLAndLine(url, line);
+    },
+
+    showSourceLine: function(url, line)
+    {
+        var scriptOrResource = this._scriptOrResourceForURLAndLine(url, line);
+        this._showScriptOrResource(scriptOrResource, {line: line, shouldHighlightLine: true});
+    },
+
+    _scriptOrResourceForURLAndLine: function(url, line)
+    {
+        var scripts = WebInspector.debuggerModel.scriptsForURL(url);
+        for (var i = 0; i < scripts.length; ++i) {
+            var script = scripts[i];
+            if (script.resource)
+                return script.resource;
+            if (script.startingLine <= line && script.startingLine + script.linesCount > line)
+                return script;
+        }
+        return null;
+    },
+
+    showView: function(view)
+    {
+        if (!view)
+            return;
+        this._showScriptOrResource(view.resource || view.script);
+    },
+
+    handleShortcut: function(event)
+    {
+        var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+        var handler = this._shortcuts[shortcut];
+        if (handler) {
+            handler(event);
+            event.handled = true;
+        } else
+            this.sidebarPanes.callstack.handleShortcut(event);
+    },
+
+    _sourceFrameForScriptOrResource: function(scriptOrResource)
+    {
+        if (scriptOrResource instanceof WebInspector.Resource)
+            return this._sourceFrameForResource(scriptOrResource);
+        return this._sourceFrameForScript(scriptOrResource);
+    },
+
+    _sourceFrameForResource: function(resource)
+    {
+        var sourceFrame = this._urlToSourceFrame[resource.url];
+        if (sourceFrame)
+            return sourceFrame;
+        var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
+        var isScript = resource.type === WebInspector.Resource.Type.Script;
+        sourceFrame = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
+        for (var i = 0; i < this._messages.length; ++i) {
+            var message = this._messages[i];
+            if (this._messages[i].url === resource.url)
+                sourceFrame.addMessage(message);
+        }
+        this._urlToSourceFrame[resource.url] = sourceFrame;
+        return sourceFrame;
+    },
+
+    _sourceFrameForScript: function(script)
+    {
+        if (script._sourceFrame)
+            return script._sourceFrame;
+        var contentProvider = new WebInspector.SourceFrameContentProviderForScript(script);
+        script._sourceFrame = new WebInspector.SourceFrame(contentProvider, script.sourceURL, true);
+        return script._sourceFrame;
+    },
+
+    _showScriptOrResource: function(scriptOrResource, options)
+    {
+        // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:}
+        options = options || {};
+
+        if (!scriptOrResource)
+            return;
+
+        var view = this._sourceFrameForScriptOrResource(scriptOrResource);
+        if (!view)
+            return;
+
+        var url = scriptOrResource.url || scriptOrResource.sourceURL;
+        if (url && !options.initialLoad)
+            WebInspector.settings.lastViewedScriptFile = url;
+
+        if (!options.fromBackForwardAction) {
+            var oldIndex = this._currentBackForwardIndex;
+            if (oldIndex >= 0)
+                this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
+
+            // Check for a previous entry of the same object in _backForwardList.
+            // If one is found, remove it and update _currentBackForwardIndex to match.
+            var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
+            if (previousEntryIndex !== -1) {
+                this._backForwardList.splice(previousEntryIndex, 1);
+                --this._currentBackForwardIndex;
+            }
+
+            this._backForwardList.push(scriptOrResource);
+            ++this._currentBackForwardIndex;
+
+            this._updateBackAndForwardButtons();
+        }
+
+        this.visibleView = view;
+
+        if (options.line) {
+            if (view.revealLine)
+                view.revealLine(options.line);
+            if (view.highlightLine && options.shouldHighlightLine)
+                view.highlightLine(options.line);
+        }
+
+        var option;
+        if (scriptOrResource instanceof WebInspector.Script) {
+            option = scriptOrResource.filesSelectOption;
+
+            // hasn't been added yet - happens for stepping in evals,
+            // so use the force option to force the script into the menu.
+            if (!option) {
+                this._addScriptToFilesMenu(scriptOrResource, true);
+                option = scriptOrResource.filesSelectOption;
+            }
+
+            console.assert(option);
+        } else
+            option = scriptOrResource.filesSelectOption;
+
+        if (option)
+            this.filesSelectElement.selectedIndex = option.index;
+    },
+
+    _addScriptToFilesMenu: function(script, force)
+    {
+        if (!script.sourceURL && !force)
+            return;
+
+        if (script.resource) {
+            if (this._resourceForURLInFilesSelect[script.resource.url])
+                return;
+            this._resourceForURLInFilesSelect[script.resource.url] = script.resource;
+        }
+
+        var displayName = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
+
+        var select = this.filesSelectElement;
+        var option = document.createElement("option");
+        option.representedObject = script.resource || script;
+        option.url = displayName;
+        option.startingLine = script.startingLine;
+        option.text = script.resource || script.startingLine === 1 ? displayName : String.sprintf("%s:%d", displayName, script.startingLine);
+
+        function optionCompare(a, b)
+        {
+            if (a.url < b.url)
+                return -1;
+            else if (a.url > b.url)
+                return 1;
+
+            if (typeof a.startingLine !== "number")
+                return -1;
+            if (typeof b.startingLine !== "number")
+                return -1;
+            return a.startingLine - b.startingLine;
+        }
+
+        var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
+        if (insertionIndex < 0)
+            select.appendChild(option);
+        else
+            select.insertBefore(option, select.childNodes.item(insertionIndex));
+
+        if (script.resource)
+            script.resource.filesSelectOption = option;
+        else
+            script.filesSelectOption = option;
+
+        if (select.options[select.selectedIndex] === option) {
+            // Call _showScriptOrResource if the option we just appended ended up being selected.
+            // This will happen for the first item added to the menu.
+            this._showScriptOrResource(option.representedObject, {initialLoad: true});
+        } else {
+            // If not first item, check to see if this was the last viewed
+            var url = option.representedObject.url || option.representedObject.sourceURL;
+            var lastURL = WebInspector.settings.lastViewedScriptFile;
+            if (url && url === lastURL) {
+                // For resources containing multiple <script> tags, we first report them separately and
+                // then glue them all together. They all share url and there is no need to show them all one
+                // by one.
+                var isResource = !!option.representedObject.url;
+                if (isResource || !this.visibleView || !this.visibleView.script || this.visibleView.script.sourceURL !== url)
+                    this._showScriptOrResource(option.representedObject, {initialLoad: true});
+            }
+        }
+
+        if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
+            script.filesSelectOption.addStyleClass("extension-script");
+    },
+
+    _clearCurrentExecutionLine: function()
+    {
+        if (this._executionSourceFrame)
+            this._executionSourceFrame.clearExecutionLocation();
+        delete this._executionSourceFrame;
+    },
+
+    _callFrameSelected: function()
+    {
+        this._clearCurrentExecutionLine();
+
+        var callStackPane = this.sidebarPanes.callstack;
+        var currentFrame = callStackPane.selectedCallFrame;
+        if (!currentFrame)
+            return;
+
+        this.sidebarPanes.scopechain.update(currentFrame);
+        this.sidebarPanes.watchExpressions.refreshExpressions();
+
+        var script = WebInspector.debuggerModel.scriptForSourceID(currentFrame.sourceID);
+        var scriptOrResource = script.resource || script;
+        this._showScriptOrResource(scriptOrResource, {line: currentFrame.line});
+
+        this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
+        if (this._executionSourceFrame)
+            this._executionSourceFrame.setExecutionLocation(currentFrame.line, currentFrame.column);
+    },
+
+    _changeVisibleFile: function(event)
+    {
+        var select = this.filesSelectElement;
+        this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
+    },
+
+    _startSidebarResizeDrag: function(event)
+    {
+        WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
+
+        if (event.target === this.sidebarResizeWidgetElement)
+            this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
+        else
+            this._dragOffset = 0;
+    },
+
+    _endSidebarResizeDrag: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+        delete this._dragOffset;
+        this.saveSidebarWidth();
+    },
+
+    _sidebarResizeDrag: function(event)
+    {
+        var x = event.pageX + this._dragOffset;
+        var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
+        this.setSidebarWidth(newWidth);
+        event.preventDefault();
+    },
+
+    setSidebarWidth: function(newWidth)
+    {
+        this.sidebarElement.style.width = newWidth + "px";
+        this.sidebarButtonsElement.style.width = newWidth + "px";
+        this.viewsContainerElement.style.right = newWidth + "px";
+        this.sidebarResizeWidgetElement.style.right = newWidth + "px";
+        this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+
+        this.resize();
+    },
+
+    _setPauseOnExceptions: function(pauseOnExceptionsState)
+    {
+        function callback(pauseOnExceptionsState)
+        {
+            if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
+                this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
+            else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
+                this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
+            else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
+                this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
+
+            this._pauseOnExceptionButton.state = pauseOnExceptionsState;
+            WebInspector.settings.pauseOnExceptionState = pauseOnExceptionsState;
+        }
+        InspectorBackend.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
+    },
+
+    _updateDebuggerButtons: function()
+    {
+        if (this._debuggerEnabled) {
+            this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
+            this.enableToggleButton.toggled = true;
+            this._pauseOnExceptionButton.visible = true;
+            this.panelEnablerView.visible = false;
+        } else {
+            this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
+            this.enableToggleButton.toggled = false;
+            this._pauseOnExceptionButton.visible = false;
+            this.panelEnablerView.visible = true;
+        }
+
+        if (this._paused) {
+            this.pauseButton.addStyleClass("paused");
+
+            this.pauseButton.disabled = false;
+            this.stepOverButton.disabled = false;
+            this.stepIntoButton.disabled = false;
+            this.stepOutButton.disabled = false;
+
+            this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
+        } else {
+            this.pauseButton.removeStyleClass("paused");
+
+            this.pauseButton.disabled = this._waitingToPause;
+            this.stepOverButton.disabled = true;
+            this.stepIntoButton.disabled = true;
+            this.stepOutButton.disabled = true;
+
+            if (this._waitingToPause)
+                this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
+            else if (this._stepping)
+                this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
+            else
+                this.debuggerStatusElement.textContent = "";
+        }
+    },
+
+    _updateBackAndForwardButtons: function()
+    {
+        this.backButton.disabled = this._currentBackForwardIndex <= 0;
+        this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
+    },
+
+    _clearInterface: function()
+    {
+        this.sidebarPanes.callstack.update(null);
+        this.sidebarPanes.scopechain.update(null);
+
+        this._clearCurrentExecutionLine();
+        this._updateDebuggerButtons();
+    },
+
+    _goBack: function()
+    {
+        if (this._currentBackForwardIndex <= 0) {
+            console.error("Can't go back from index " + this._currentBackForwardIndex);
+            return;
+        }
+
+        this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true});
+        this._updateBackAndForwardButtons();
+    },
+
+    _goForward: function()
+    {
+        if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
+            console.error("Can't go forward from index " + this._currentBackForwardIndex);
+            return;
+        }
+
+        this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true});
+        this._updateBackAndForwardButtons();
+    },
+
+    _formatScript: function()
+    {
+        if (this.visibleView)
+            this.visibleView.formatSource();
+    },
+
+    _enableDebugging: function()
+    {
+        if (this._debuggerEnabled)
+            return;
+        this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
+    },
+
+    _toggleDebugging: function(optionalAlways)
+    {
+        this._paused = false;
+        this._waitingToPause = false;
+        this._stepping = false;
+
+        if (this._debuggerEnabled) {
+            WebInspector.settings.debuggerEnabled = false;
+            WebInspector.debuggerModel.disableDebugger();
+        } else {
+            WebInspector.settings.debuggerEnabled = !!optionalAlways;
+            WebInspector.debuggerModel.enableDebugger();
+        }
+    },
+
+    _togglePauseOnExceptions: function()
+    {
+        this._setPauseOnExceptions((this._pauseOnExceptionButton.state + 1) % this._pauseOnExceptionButton.states);
+    },
+
+    _togglePause: function()
+    {
+        if (this._paused) {
+            this._paused = false;
+            this._waitingToPause = false;
+            InspectorBackend.resume();
+        } else {
+            this._stepping = false;
+            this._waitingToPause = true;
+            InspectorBackend.pause();
+        }
+
+        this._clearInterface();
+    },
+
+    _stepOverClicked: function()
+    {
+        this._paused = false;
+        this._stepping = true;
+
+        this._clearInterface();
+
+        InspectorBackend.stepOver();
+    },
+
+    _stepIntoClicked: function()
+    {
+        this._paused = false;
+        this._stepping = true;
+
+        this._clearInterface();
+
+        InspectorBackend.stepInto();
+    },
+
+    _stepOutClicked: function()
+    {
+        this._paused = false;
+        this._stepping = true;
+
+        this._clearInterface();
+
+        InspectorBackend.stepOut();
+    },
+
+    toggleBreakpointsClicked: function()
+    {
+        this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
+        if (this.toggleBreakpointsButton.toggled) {
+            InspectorBackend.activateBreakpoints();
+            this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
+            document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
+        } else {
+            InspectorBackend.deactivateBreakpoints();
+            this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
+            document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
+        }
+    },
+
+    elementsToRestoreScrollPositionsFor: function()
+    {
+        return [ this.sidebarElement ];
+    },
+
+    _registerShortcuts: function()
+    {
+        var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Scripts Panel"));
+        var handler, shortcut1, shortcut2;
+        var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
+
+        this._shortcuts = {};
+
+        // Continue.
+        handler = this.pauseButton.click.bind(this.pauseButton);
+        shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8);
+        this._shortcuts[shortcut1.key] = handler;
+        shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier);
+        this._shortcuts[shortcut2.key] = handler;
+        section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Continue"));
+
+        // Step over.
+        handler = this.stepOverButton.click.bind(this.stepOverButton);
+        shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10);
+        this._shortcuts[shortcut1.key] = handler;
+        shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier);
+        this._shortcuts[shortcut2.key] = handler;
+        section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step over"));
+
+        // Step into.
+        handler = this.stepIntoButton.click.bind(this.stepIntoButton);
+        shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11);
+        this._shortcuts[shortcut1.key] = handler;
+        shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier);
+        this._shortcuts[shortcut2.key] = handler;
+        section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step into"));
+
+        // Step out.
+        handler = this.stepOutButton.click.bind(this.stepOutButton);
+        shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift);
+        this._shortcuts[shortcut1.key] = handler;
+        shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier);
+        this._shortcuts[shortcut2.key] = handler;
+        section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step out"));
+
+        var isMac = WebInspector.isMac();
+        if (isMac)
+            shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Meta);
+        else
+            shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor("g", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+        this._shortcuts[shortcut1.key] = this.showGoToLineDialog.bind(this);
+        section.addAlternateKeys([ shortcut1.name ], WebInspector.UIString("Go to Line"));
+        this.sidebarPanes.callstack.registerShortcuts(section);
+    },
+
+    searchCanceled: function()
+    {
+        WebInspector.updateSearchMatchesCount(0, this);
+
+        if (this._searchView)
+            this._searchView.searchCanceled();
+
+        delete this._searchView;
+        delete this._searchQuery;
+    },
+
+    performSearch: function(query)
+    {
+        if (!this.visibleView)
+            return;
+
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled();
+
+        this._searchView = this.visibleView;
+        this._searchQuery = query;
+
+        function finishedCallback(view, searchMatches)
+        {
+            if (!searchMatches)
+                return;
+
+            WebInspector.updateSearchMatchesCount(searchMatches, this);
+            view.jumpToFirstSearchResult();
+        }
+
+        this._searchView.performSearch(query, finishedCallback.bind(this));
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        if (!this._searchView)
+            return;
+
+        if (this._searchView !== this.visibleView) {
+            this.performSearch(this._searchQuery);
+            return;
+        }
+
+        if (this._searchView.showingLastSearchResult())
+            this._searchView.jumpToFirstSearchResult();
+        else
+            this._searchView.jumpToNextSearchResult();
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        if (!this._searchView)
+            return;
+
+        if (this._searchView !== this.visibleView) {
+            this.performSearch(this._searchQuery);
+            if (this._searchView)
+                this._searchView.jumpToLastSearchResult();
+            return;
+        }
+
+        if (this._searchView.showingFirstSearchResult())
+            this._searchView.jumpToLastSearchResult();
+        else
+            this._searchView.jumpToPreviousSearchResult();
+    },
+
+    showGoToLineDialog: function(e)
+    {
+         var view = this.visibleView;
+         if (view)
+             WebInspector.GoToLineDialog.show(view);
+    }
+}
+
+WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+
+WebInspector.SourceFrameContentProviderForScript = function(script)
+{
+    WebInspector.SourceFrameContentProvider.call(this);
+    this._script = script;
+}
+
+WebInspector.SourceFrameContentProviderForScript.prototype = {
+    requestContent: function(callback)
+    {
+        function didRequestSource(source)
+        {
+            if (source) {
+                var prefix = "";
+                for (var i = 0; i < this._script.lineOffset; ++i)
+                    prefix += "\n";
+                source = prefix + source;
+            } else
+                source = WebInspector.UIString("<source is not available>");
+
+            var sourceMapping = new WebInspector.IdenticalSourceMapping();
+            var scriptRanges = WebInspector.ScriptFormatter.findScriptRanges(source.lineEndings(), [this._script]);
+            callback("text/javascript", new WebInspector.SourceFrameContent(source, sourceMapping, scriptRanges));
+        }
+        this._script.requestSource(didRequestSource.bind(this));
+    }
+}
+
+WebInspector.SourceFrameContentProviderForScript.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Section.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Section.js
new file mode 100644
index 0000000..5caa78b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Section.js
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Google Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Section = function(title, subtitle)
+{
+    this.element = document.createElement("div");
+    this.element.className = "section";
+    this.element._section = this;
+
+    this.headerElement = document.createElement("div");
+    this.headerElement.className = "header";
+
+    this.titleElement = document.createElement("div");
+    this.titleElement.className = "title";
+
+    this.subtitleElement = document.createElement("div");
+    this.subtitleElement.className = "subtitle";
+
+    this.headerElement.appendChild(this.subtitleElement);
+    this.headerElement.appendChild(this.titleElement);
+
+    this.headerElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+    this.element.appendChild(this.headerElement);
+
+    this.title = title;
+    this.subtitle = subtitle;
+    this._expanded = false;
+}
+
+WebInspector.Section.prototype = {
+    get title()
+    {
+        return this._title;
+    },
+
+    set title(x)
+    {
+        if (this._title === x)
+            return;
+        this._title = x;
+
+        if (x instanceof Node) {
+            this.titleElement.removeChildren();
+            this.titleElement.appendChild(x);
+        } else
+          this.titleElement.textContent = x;
+    },
+
+    get subtitle()
+    {
+        return this._subtitle;
+    },
+
+    set subtitle(x)
+    {
+        if (this._subtitle === x)
+            return;
+        this._subtitle = x;
+        this.subtitleElement.textContent = x;
+    },
+
+    get subtitleAsTextForTest()
+    {
+        var result = this.subtitleElement.textContent;
+        var child = this.subtitleElement.querySelector("[data-uncopyable]");
+        if (child) {
+            var linkData = child.getAttribute("data-uncopyable");
+            if (linkData)
+                result += linkData;
+        }
+        return result;
+    },
+
+    get expanded()
+    {
+        return this._expanded;
+    },
+
+    set expanded(x)
+    {
+        if (x)
+            this.expand();
+        else
+            this.collapse();
+    },
+
+    get populated()
+    {
+        return this._populated;
+    },
+
+    set populated(x)
+    {
+        this._populated = x;
+        if (!x && this.onpopulate && this._expanded) {
+            this.onpopulate(this);
+            this._populated = true;
+        }
+    },
+
+    get nextSibling()
+    {
+        var curElement = this.element;
+        do {
+            curElement = curElement.nextSibling;
+        } while (curElement && !curElement._section);
+
+        return curElement ? curElement._section : null;
+    },
+
+    get previousSibling()
+    {
+        var curElement = this.element;
+        do {
+            curElement = curElement.previousSibling;
+        } while (curElement && !curElement._section);
+
+        return curElement ? curElement._section : null;
+    },
+
+    expand: function()
+    {
+        if (this._expanded)
+            return;
+        this._expanded = true;
+        this.element.addStyleClass("expanded");
+
+        if (!this._populated && this.onpopulate) {
+            this.onpopulate(this);
+            this._populated = true;
+        }
+    },
+
+    collapse: function()
+    {
+        if (!this._expanded)
+            return;
+        this._expanded = false;
+        this.element.removeStyleClass("expanded");
+    },
+
+    toggleExpanded: function()
+    {
+        this.expanded = !this.expanded;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/Settings.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Settings.js
new file mode 100644
index 0000000..68b81a5
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/Settings.js
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+var Preferences = {
+    canEditScriptSource: false,
+    maxInlineTextChildLength: 80,
+    minConsoleHeight: 75,
+    minSidebarWidth: 100,
+    minElementsSidebarWidth: 200,
+    minScriptsSidebarWidth: 200,
+    styleRulesExpandedState: {},
+    showMissingLocalizedStrings: false,
+    samplingCPUProfiler: false,
+    showColorNicknames: true,
+    debuggerAlwaysEnabled: false,
+    profilerAlwaysEnabled: false,
+    onlineDetectionEnabled: true,
+    nativeInstrumentationEnabled: false,
+    resourceExportEnabled: false,
+    useDataURLForResourceImageIcons: true,
+    showTimingTab: false,
+    showCookiesTab: false,
+    debugMode: false,
+    heapProfilerPresent: false,
+    detailedHeapProfiles: false
+}
+
+WebInspector.Settings = function()
+{
+    this.installApplicationSetting("colorFormat", "hex");
+    this.installApplicationSetting("consoleHistory", []);
+    this.installApplicationSetting("debuggerEnabled", false);
+    this.installApplicationSetting("profilerEnabled", false);
+    this.installApplicationSetting("eventListenersFilter", "all");
+    this.installApplicationSetting("lastActivePanel", "elements");
+    this.installApplicationSetting("lastViewedScriptFile", "application");
+    this.installApplicationSetting("monitoringXHREnabled", false);
+    this.installApplicationSetting("pauseOnExceptionState", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions);
+    this.installApplicationSetting("resourcesLargeRows", true);
+    this.installApplicationSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
+    this.installApplicationSetting("resourceViewTab", "content");
+    this.installApplicationSetting("showInheritedComputedStyleProperties", false);
+    this.installApplicationSetting("showUserAgentStyles", true);
+    this.installApplicationSetting("watchExpressions", []);
+    this.installApplicationSetting("breakpoints", []);
+
+    this.installProjectSetting("nativeBreakpoints", []);
+}
+
+WebInspector.Settings.Events = {
+    ProjectChanged: "project-changed"
+}
+
+WebInspector.Settings.prototype = {
+    installApplicationSetting: function(key, defaultValue)
+    {
+        if (key in this)
+            return;
+
+        this.__defineGetter__(key, this._get.bind(this, key, defaultValue));
+        this.__defineSetter__(key, this._set.bind(this, key));
+    },
+
+    installProjectSetting: function(key, defaultValue)
+    {
+        this.__defineGetter__(key, this._getProjectSetting.bind(this, key, defaultValue));
+        this.__defineSetter__(key, this._setProjectSetting.bind(this, key));
+    },
+
+    inspectedURLChanged: function(url)
+    {
+        var fragmentIndex = url.indexOf("#");
+        if (fragmentIndex !== -1)
+            url = url.substring(0, fragmentIndex);
+        this._projectId = url;
+        this.dispatchEventToListeners(WebInspector.Settings.Events.ProjectChanged);
+    },
+
+    get projectId()
+    {
+        return this._projectId;
+    },
+
+    findSettingForAllProjects: function(key)
+    {
+        var result = {};
+        var regexp = "^" + key + ":(.*)";
+        for (var i = 0; i < window.localStorage.length; ++i) {
+            var fullKey =  window.localStorage.key(i);
+            var match = fullKey.match(regexp);
+            if (!match)
+                continue;
+            try {
+                result[match[1]] = JSON.parse(window.localStorage[fullKey]);
+            } catch(e) {
+                window.localStorage.removeItem(fullKey);
+            }
+        }
+        return result;
+    },
+
+    _get: function(key, defaultValue)
+    {
+        if (key in window.localStorage) {
+            try {
+                return JSON.parse(window.localStorage[key]);
+            } catch(e) {
+                window.localStorage.removeItem(key);
+            }
+        }
+        return defaultValue;
+    },
+
+    _set: function(key, value)
+    {
+        window.localStorage[key] = JSON.stringify(value);
+    },
+
+    _getProjectSetting: function(key, defaultValue)
+    {
+        return this._get(this._formatProjectKey(key), defaultValue);
+    },
+
+    _setProjectSetting: function(key, value)
+    {
+        return this._set(this._formatProjectKey(key), value);
+    },
+
+    _formatProjectKey: function(key)
+    {
+        return key + ":" + this._projectId;
+    }
+}
+
+WebInspector.Settings.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShortcutsHelp.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShortcutsHelp.js
new file mode 100644
index 0000000..004ed48
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShortcutsHelp.js
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ShortcutsHelp = function()
+{
+    this._sections = {};
+}
+
+WebInspector.ShortcutsHelp.prototype = {
+    section: function(name)
+    {
+        var section = this._sections[name];
+        if (!section)
+            this._sections[name] = section = new WebInspector.ShortcutsSection(name);
+        return section;
+    },
+
+    show: function()
+    {
+        if (!this._helpScreen) {
+            this._helpScreen = new WebInspector.HelpScreen(WebInspector.UIString("Keyboard Shortcuts"));
+            this._buildTable(this._helpScreen.contentElement, 2);
+        }
+        this._helpScreen.show();
+    },
+
+    _buildTable: function(parent, nColumns)
+    {
+        var height = 0;
+        var orderedSections = [];
+        for (var section in this._sections) {
+            height += this._sections[section]._height;
+            orderedSections.push(this._sections[section])
+        }
+        function compareSections(a, b)
+        {
+            return a.order - b.order;
+        }
+        orderedSections = orderedSections.sort(compareSections);
+
+        const wrapAfter = height / nColumns;
+        var table = document.createElement("table");
+        table.className = "help-table";
+        var row = table.createChild("tr");
+
+        // This manual layout ugliness should be gone once WebKit implements
+        // pagination hints for CSS columns (break-inside etc).
+        for (var section = 0; section < orderedSections.length;) {
+            var td = row.createChild("td");
+            td.style.width = (100 / nColumns) + "%";
+            var column = td.createChild("table");
+            for (var columnHeight = 0;
+                columnHeight < wrapAfter && section < orderedSections.length;
+                columnHeight += orderedSections[section]._height, section++) {
+                orderedSections[section].renderSection(column);
+            }
+        }
+        parent.appendChild(table);
+    }
+};
+
+WebInspector.shortcutsHelp = new WebInspector.ShortcutsHelp();
+
+WebInspector.ShortcutsSection = function(name)
+{
+    this.name = name;
+    this._lines = [];
+    this.order = ++WebInspector.ShortcutsSection._sequenceNumber;
+};
+
+WebInspector.ShortcutsSection._sequenceNumber = 0;
+
+WebInspector.ShortcutsSection.prototype = {
+    addKey: function(key, description)
+    {
+        this.addLine(this._renderKey(key), description);
+    },
+
+    addRelatedKeys: function(keys, description)
+    {
+        this.addLine(this._renderSequence(keys,"/"), description);
+    },
+
+    addAlternateKeys: function(keys, description)
+    {
+        this.addLine(this._renderSequence(keys,WebInspector.UIString("or")), description);
+    },
+
+    addLine: function(htmlKey, description)
+    {
+        this._lines.push({ key: htmlKey, text: description })
+    },
+
+    renderSection: function(parent)
+    {
+        this._renderHeader(parent);
+
+        for (var line = 0; line < this._lines.length; ++line) {
+            var tr = parent.createChild("tr");
+            tr.createChild("td", "help-key-cell").innerHTML = this._lines[line].key + " : ";
+            tr.createChild("td").innerText = this._lines[line].text;
+        }
+    },
+
+    _renderHeader: function(parent)
+    {
+        var trHead = parent.createChild("tr");
+ 
+        trHead.createChild("th");
+        trHead.createChild("th").innerText = this.name;
+    },
+
+    _renderSequence: function(sequence, delimiter)
+    {
+        var delimiterHtml = '<span class="help-key-delimiter">' + delimiter.escapeHTML() + '</span>'
+        return sequence.map(this._renderKey).join(delimiterHtml);
+    },
+
+    _renderKey: function(key)
+    {
+        function renderLabel(label)
+        {
+            return '<span class="help-key monospace">' + label.escapeHTML() + '</span>';
+        }
+        return key.split(" + ").map(renderLabel).join('<span class="help-combine-keys">+</span>');
+    },
+
+    get _height()
+    {
+        return this._lines.length + 2; // add some space for header
+    }
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShowMoreDataGridNode.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShowMoreDataGridNode.js
new file mode 100644
index 0000000..4fe2fef
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/ShowMoreDataGridNode.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ShowMoreDataGridNode = function(callback, nextCount, allCount)
+{
+    function populate(count)
+    {
+        var index = this.parent.children.indexOf(this);
+        this.parent.removeChild(this);
+        callback(count, index);
+    }
+
+    this.showNext = document.createElement("button");
+    this.showNext.setAttribute("type", "button");
+    this.showNext.textContent = WebInspector.UIString("Show next %d", nextCount);
+    this.showNext.addEventListener("click", populate.bind(this, nextCount), false);
+
+    if (allCount) {
+        this.showAll = document.createElement("button");
+        this.showAll.setAttribute("type", "button");
+        this.showAll.textContent = WebInspector.UIString("Show all %d", allCount);
+        this.showAll.addEventListener("click", populate.bind(this, allCount), false);
+    }
+
+    WebInspector.DataGridNode.call(this, {summaryRow:true}, false);
+    this.selectable = false;
+}
+
+WebInspector.ShowMoreDataGridNode.prototype = {
+    createCells: function()
+    {
+        var cell = document.createElement("td");
+        if (this.depth)
+            cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+        cell.appendChild(this.showNext);
+        if (this.showAll)
+            cell.appendChild(this.showAll);
+        this._element.appendChild(cell);
+
+        var columns = this.dataGrid.columns;
+        var count = 0;
+        for (var c in columns)
+            ++count;
+        while (--count > 0) {
+            cell = document.createElement("td");
+            this._element.appendChild(cell);
+        }
+    }
+};
+
+WebInspector.ShowMoreDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarPane.js
new file mode 100644
index 0000000..ebc62db
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarPane.js
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarPane = function(title)
+{
+    this.element = document.createElement("div");
+    this.element.className = "pane";
+
+    this.titleElement = document.createElement("div");
+    this.titleElement.className = "title";
+    this.titleElement.tabIndex = 0;
+    this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+    this.titleElement.addEventListener("keydown", this._onTitleKeyDown.bind(this), false);
+
+    this.bodyElement = document.createElement("div");
+    this.bodyElement.className = "body";
+
+    this.element.appendChild(this.titleElement);
+    this.element.appendChild(this.bodyElement);
+
+    this.title = title;
+    this.growbarVisible = false;
+    this.expanded = false;
+}
+
+WebInspector.SidebarPane.prototype = {
+    get title()
+    {
+        return this._title;
+    },
+
+    set title(x)
+    {
+        if (this._title === x)
+            return;
+        this._title = x;
+        this.titleElement.textContent = x;
+    },
+
+    get growbarVisible()
+    {
+        return this._growbarVisible;
+    },
+
+    set growbarVisible(x)
+    {
+        if (this._growbarVisible === x)
+            return;
+
+        this._growbarVisible = x;
+
+        if (x && !this._growbarElement) {
+            this._growbarElement = document.createElement("div");
+            this._growbarElement.className = "growbar";
+            this.element.appendChild(this._growbarElement);
+        } else if (!x && this._growbarElement) {
+            if (this._growbarElement.parentNode)
+                this._growbarElement.parentNode(this._growbarElement);
+            delete this._growbarElement;
+        }
+    },
+
+    get expanded()
+    {
+        return this._expanded;
+    },
+
+    set expanded(x)
+    {
+        if (x)
+            this.expand();
+        else
+            this.collapse();
+    },
+
+    expand: function()
+    {
+        if (this._expanded)
+            return;
+        this._expanded = true;
+        this.element.addStyleClass("expanded");
+        if (this.onexpand)
+            this.onexpand(this);
+    },
+
+    collapse: function()
+    {
+        if (!this._expanded)
+            return;
+        this._expanded = false;
+        this.element.removeStyleClass("expanded");
+        if (this.oncollapse)
+            this.oncollapse(this);
+    },
+
+    toggleExpanded: function()
+    {
+        this.expanded = !this.expanded;
+    },
+
+    _onTitleKeyDown: function(event)
+    {
+        if (isEnterKey(event) || event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code)
+            this.toggleExpanded();
+    }
+}
+
+WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarTreeElement.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarTreeElement.js
new file mode 100644
index 0000000..a27c457
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SidebarTreeElement.js
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren)
+{
+    TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren);
+}
+
+WebInspector.SidebarSectionTreeElement.prototype = {
+    selectable: false,
+
+    get smallChildren()
+    {
+        return this._smallChildren;
+    },
+
+    set smallChildren(x)
+    {
+        if (this._smallChildren === x)
+            return;
+
+        this._smallChildren = x;
+
+        if (this._smallChildren)
+            this._childrenListNode.addStyleClass("small");
+        else
+            this._childrenListNode.removeStyleClass("small");
+    },
+
+    onattach: function()
+    {
+        this._listItemNode.addStyleClass("sidebar-tree-section");
+    },
+
+    onreveal: function()
+    {
+        if (this.listItemElement)
+            this.listItemElement.scrollIntoViewIfNeeded(false);
+    }
+}
+
+WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren)
+{
+    TreeElement.call(this, "", representedObject || {}, hasChildren);
+
+    if (hasChildren) {
+        this.disclosureButton = document.createElement("button");
+        this.disclosureButton.className = "disclosure-button";
+    }
+
+    if (!this.iconElement) {
+        this.iconElement = document.createElement("img");
+        this.iconElement.className = "icon";
+    }
+
+    this.statusElement = document.createElement("div");
+    this.statusElement.className = "status";
+
+    this.titlesElement = document.createElement("div");
+    this.titlesElement.className = "titles";
+
+    this.titleElement = document.createElement("span");
+    this.titleElement.className = "title";
+    this.titlesElement.appendChild(this.titleElement);
+
+    this.subtitleElement = document.createElement("span");
+    this.subtitleElement.className = "subtitle";
+    this.titlesElement.appendChild(this.subtitleElement);
+
+    this.className = className;
+    this.mainTitle = title;
+    this.subtitle = subtitle;
+}
+
+WebInspector.SidebarTreeElement.prototype = {
+    get small()
+    {
+        return this._small;
+    },
+
+    set small(x)
+    {
+        this._small = x;
+
+        if (this._listItemNode) {
+            if (this._small)
+                this._listItemNode.addStyleClass("small");
+            else
+                this._listItemNode.removeStyleClass("small");
+        }
+    },
+
+    get mainTitle()
+    {
+        return this._mainTitle;
+    },
+
+    set mainTitle(x)
+    {
+        this._mainTitle = x;
+        this.refreshTitles();
+    },
+
+    get subtitle()
+    {
+        return this._subtitle;
+    },
+
+    set subtitle(x)
+    {
+        this._subtitle = x;
+        this.refreshTitles();
+    },
+
+    get bubbleText()
+    {
+        return this._bubbleText;
+    },
+
+    set bubbleText(x)
+    {
+        if (!this.bubbleElement) {
+            this.bubbleElement = document.createElement("div");
+            this.bubbleElement.className = "bubble";
+            this.statusElement.appendChild(this.bubbleElement);
+        }
+
+        this._bubbleText = x;
+        this.bubbleElement.textContent = x;
+    },
+
+    refreshTitles: function()
+    {
+        var mainTitle = this.mainTitle;
+        if (this.titleElement.textContent !== mainTitle)
+            this.titleElement.textContent = mainTitle;
+
+        var subtitle = this.subtitle;
+        if (subtitle) {
+            if (this.subtitleElement.textContent !== subtitle)
+                this.subtitleElement.textContent = subtitle;
+            this.titlesElement.removeStyleClass("no-subtitle");
+        } else {
+            this.subtitleElement.textContent = "";
+            this.titlesElement.addStyleClass("no-subtitle");
+        }
+    },
+
+    isEventWithinDisclosureTriangle: function(event)
+    {
+        return event.target === this.disclosureButton;
+    },
+
+    onattach: function()
+    {
+        this._listItemNode.addStyleClass("sidebar-tree-item");
+
+        if (this.className)
+            this._listItemNode.addStyleClass(this.className);
+
+        if (this.small)
+            this._listItemNode.addStyleClass("small");
+
+        if (this.hasChildren && this.disclosureButton)
+            this._listItemNode.appendChild(this.disclosureButton);
+
+        this._listItemNode.appendChild(this.iconElement);
+        this._listItemNode.appendChild(this.statusElement);
+        this._listItemNode.appendChild(this.titlesElement);
+    },
+
+    onreveal: function()
+    {
+        if (this._listItemNode)
+            this._listItemNode.scrollIntoViewIfNeeded(false);
+    }
+}
+
+WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.js
new file mode 100644
index 0000000..7259dc1
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.js
@@ -0,0 +1,1423 @@
+/* Generated by re2c 0.13.5 on Mon Dec 20 18:44:30 2010 */
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceCSSTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: case 1: var yych|'
+
+WebInspector.SourceCSSTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    this._propertyKeywords = WebInspector.cssNameCompletions.keySet();
+
+    this._valueKeywords = [
+        "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll",
+        "alternate", "always","amharic", "amharic-abegede", "antialiased", "appworkspace", "aqua", "arabic-indic", "armenian", "asterisks",
+        "auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "black", "blink",
+        "block", "block-axis", "blue", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button",
+        "button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator",
+        "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic",
+        "clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu",
+        "continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default",
+        "default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document",
+        "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element",
+        "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez",
+        "ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et",
+        "ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et",
+        "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded",
+        "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "fuchsia", "geometricPrecision",
+        "georgian", "gray", "graytext", "green", "grey", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help",
+        "hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
+        "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline",
+        "inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana",
+        "katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "lime", "line-through", "linear", "lines",
+        "list-button", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek",
+        "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "maroon", "match", "media-controls-background",
+        "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button",
+        "media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display",
+        "media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button",
+        "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple",
+        "myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none",
+        "normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "olive", "open-quote", "optimizeLegibility",
+        "optimizeSpeed", "orange", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused",
+        "persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "purple",
+        "push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "red", "relative", "repeat", "repeat-x",
+        "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif",
+        "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
+        "searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "silver", "single",
+        "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
+        "small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over",
+        "space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super",
+        "sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group",
+        "table-row", "table-row-group", "teal", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin",
+        "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede",
+        "tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian",
+        "upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible",
+        "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext",
+        "x-large", "x-small", "xor", "xx-large", "xx-small", "yellow", "-wap-marquee", "-webkit-activelink", "-webkit-auto", "-webkit-baseline-middle",
+        "-webkit-body", "-webkit-box", "-webkit-center", "-webkit-control", "-webkit-focus-ring-color", "-webkit-grab", "-webkit-grabbing",
+        "-webkit-gradient", "-webkit-inline-box", "-webkit-left", "-webkit-link", "-webkit-marquee", "-webkit-mini-control", "-webkit-nowrap", "-webkit-right",
+        "-webkit-small-control", "-webkit-text", "-webkit-xxx-large", "-webkit-zoom-in", "-webkit-zoom-out",
+    ].keySet();
+
+    this._mediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet();
+
+    this._lexConditions = {
+        INITIAL: 0,
+        COMMENT: 1,
+        DSTRING: 2,
+        SSTRING: 3
+    };
+
+    this._parseConditions = {
+        INITIAL: 0,
+        PROPERTY: 1,
+        PROPERTY_VALUE: 2,
+        AT_RULE: 3
+    };
+
+    this.case_INITIAL = 1000;
+    this.case_COMMENT = 1002;
+    this.case_DSTRING = 1003;
+    this.case_SSTRING = 1004;
+
+    this.initialCondition = { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }
+}
+
+WebInspector.SourceCSSTokenizer.prototype = {
+    _stringToken: function(cursor, stringEnds)
+    {
+        if (this._isPropertyValue())
+            this.tokenType = "css-string";
+        else
+            this.tokenType = null;
+        return cursor;
+    },
+
+    _isPropertyValue: function()
+    {
+        return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE;
+    },
+
+    nextToken: function(cursor)
+    {
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            
+        {
+            case 1: var yych;
+            var yyaccept = 0;
+            if (this.getLexCondition() < 2) {
+                if (this.getLexCondition() < 1) {
+                    { gotoCase = this.case_INITIAL; continue; };
+                } else {
+                    { gotoCase = this.case_COMMENT; continue; };
+                }
+            } else {
+                if (this.getLexCondition() < 3) {
+                    { gotoCase = this.case_DSTRING; continue; };
+                } else {
+                    { gotoCase = this.case_SSTRING; continue; };
+                }
+            }
+/* *********************************** */
+case this.case_COMMENT:
+
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 4; continue; };
+                { gotoCase = 3; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 4; continue; };
+                if (yych == '*') { gotoCase = 6; continue; };
+                { gotoCase = 3; continue; };
+            }
+case 2:
+            { this.tokenType = "css-comment"; return cursor; }
+case 3:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 12; continue; };
+case 4:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 6:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '*') { gotoCase = 9; continue; };
+            if (yych != '/') { gotoCase = 11; continue; };
+case 7:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.INITIAL);
+            { this.tokenType = "css-comment"; return cursor; }
+case 9:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '*') { gotoCase = 9; continue; };
+            if (yych == '/') { gotoCase = 7; continue; };
+case 11:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 12:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 2; continue; };
+                { gotoCase = 11; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 2; continue; };
+                if (yych == '*') { gotoCase = 9; continue; };
+                { gotoCase = 11; continue; };
+            }
+/* *********************************** */
+case this.case_DSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 17; continue; };
+                if (yych <= '\f') { gotoCase = 16; continue; };
+                { gotoCase = 17; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 16; continue; };
+                    { gotoCase = 19; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 21; continue; };
+                    { gotoCase = 16; continue; };
+                }
+            }
+case 15:
+            { return this._stringToken(cursor); }
+case 16:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 23; continue; };
+case 17:
+            ++cursor;
+case 18:
+            { this.tokenType = null; return cursor; }
+case 19:
+            ++cursor;
+case 20:
+            this.setLexCondition(this._lexConditions.INITIAL);
+            { return this._stringToken(cursor, true); }
+case 21:
+            yych = this._charAt(++cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 22; continue; };
+                    if (yych <= '&') { gotoCase = 18; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 18; continue; };
+                    } else {
+                        if (yych != 'b') { gotoCase = 18; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych >= 'g') { gotoCase = 18; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 22; continue; };
+                        if (yych <= 'q') { gotoCase = 18; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 18; continue; };
+                    } else {
+                        if (yych != 'v') { gotoCase = 18; continue; };
+                    }
+                }
+            }
+case 22:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 23:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 15; continue; };
+                if (yych <= '\f') { gotoCase = 22; continue; };
+                { gotoCase = 15; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 22; continue; };
+                    { gotoCase = 26; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 22; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 22; continue; };
+                    if (yych >= '\'') { gotoCase = 22; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych >= '\\') { gotoCase = 22; continue; };
+                    } else {
+                        if (yych == 'b') { gotoCase = 22; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych <= 'f') { gotoCase = 22; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 22; continue; };
+                        if (yych >= 'r') { gotoCase = 22; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych >= 't') { gotoCase = 22; continue; };
+                    } else {
+                        if (yych == 'v') { gotoCase = 22; continue; };
+                    }
+                }
+            }
+            cursor = YYMARKER;
+            { gotoCase = 15; continue; };
+case 26:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 20; continue; };
+/* *********************************** */
+case this.case_INITIAL:
+            yych = this._charAt(cursor);
+            if (yych <= ';') {
+                if (yych <= '\'') {
+                    if (yych <= '"') {
+                        if (yych <= ' ') { gotoCase = 29; continue; };
+                        if (yych <= '!') { gotoCase = 31; continue; };
+                        { gotoCase = 33; continue; };
+                    } else {
+                        if (yych == '$') { gotoCase = 31; continue; };
+                        if (yych >= '\'') { gotoCase = 34; continue; };
+                    }
+                } else {
+                    if (yych <= '.') {
+                        if (yych <= ',') { gotoCase = 29; continue; };
+                        if (yych <= '-') { gotoCase = 35; continue; };
+                        { gotoCase = 36; continue; };
+                    } else {
+                        if (yych <= '/') { gotoCase = 37; continue; };
+                        if (yych <= '9') { gotoCase = 38; continue; };
+                        if (yych <= ':') { gotoCase = 40; continue; };
+                        { gotoCase = 42; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '^') {
+                    if (yych <= '?') {
+                        if (yych == '=') { gotoCase = 31; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 29; continue; };
+                        if (yych <= ']') { gotoCase = 31; continue; };
+                    }
+                } else {
+                    if (yych <= 'z') {
+                        if (yych != '`') { gotoCase = 31; continue; };
+                    } else {
+                        if (yych <= '{') { gotoCase = 44; continue; };
+                        if (yych == '}') { gotoCase = 46; continue; };
+                    }
+                }
+            }
+case 29:
+            ++cursor;
+case 30:
+            { this.tokenType = null; return cursor; }
+case 31:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 49; continue; };
+case 32:
+            {
+                    var token = this._line.substring(cursorOnEnter, cursor);
+                    if (this._condition.parseCondition === this._parseConditions.INITIAL) {
+                        if (token === "@import" || token === "@media") {
+                            this.tokenType = "css-at-rule";
+                            this._condition.parseCondition = this._parseConditions.AT_RULE;
+                        } else if (token.indexOf("@") === 0)
+                            this.tokenType = "css-at-rule";
+                        else
+                            this.tokenType = "css-selector";
+                    }
+                    else if (this._condition.parseCondition === this._parseConditions.AT_RULE && token in this._mediaTypes)
+                        this.tokenType = "css-keyword";
+                    else if (this._condition.parseCondition === this._parseConditions.PROPERTY && token in this._propertyKeywords)
+                        this.tokenType = "css-property";
+                    else if (this._isPropertyValue() && token in this._valueKeywords)
+                        this.tokenType = "css-keyword";
+                    else if (token === "!important")
+                        this.tokenType = "css-important";
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+case 33:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '-') {
+                if (yych <= '!') {
+                    if (yych <= '\f') {
+                        if (yych == '\n') { gotoCase = 32; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych <= '\r') { gotoCase = 32; continue; };
+                        if (yych <= ' ') { gotoCase = 124; continue; };
+                        { gotoCase = 122; continue; };
+                    }
+                } else {
+                    if (yych <= '$') {
+                        if (yych <= '"') { gotoCase = 114; continue; };
+                        if (yych <= '#') { gotoCase = 124; continue; };
+                        { gotoCase = 122; continue; };
+                    } else {
+                        if (yych == '\'') { gotoCase = 122; continue; };
+                        if (yych <= ',') { gotoCase = 124; continue; };
+                        { gotoCase = 122; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '<') {
+                        if (yych <= '.') { gotoCase = 124; continue; };
+                        if (yych <= '9') { gotoCase = 122; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych <= '=') { gotoCase = 122; continue; };
+                        if (yych <= '?') { gotoCase = 124; continue; };
+                        { gotoCase = 122; continue; };
+                    }
+                } else {
+                    if (yych <= '^') {
+                        if (yych <= '\\') { gotoCase = 126; continue; };
+                        if (yych <= ']') { gotoCase = 122; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych == '`') { gotoCase = 124; continue; };
+                        if (yych <= 'z') { gotoCase = 122; continue; };
+                        { gotoCase = 124; continue; };
+                    }
+                }
+            }
+case 34:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '-') {
+                if (yych <= '"') {
+                    if (yych <= '\f') {
+                        if (yych == '\n') { gotoCase = 32; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '\r') { gotoCase = 32; continue; };
+                        if (yych <= ' ') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                } else {
+                    if (yych <= '&') {
+                        if (yych == '$') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '\'') { gotoCase = 114; continue; };
+                        if (yych <= ',') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '<') {
+                        if (yych <= '.') { gotoCase = 116; continue; };
+                        if (yych <= '9') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '=') { gotoCase = 112; continue; };
+                        if (yych <= '?') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                } else {
+                    if (yych <= '^') {
+                        if (yych <= '\\') { gotoCase = 118; continue; };
+                        if (yych <= ']') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych == '`') { gotoCase = 116; continue; };
+                        if (yych <= 'z') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    }
+                }
+            }
+case 35:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '.') { gotoCase = 65; continue; };
+            if (yych <= '/') { gotoCase = 49; continue; };
+            if (yych <= '9') { gotoCase = 50; continue; };
+            { gotoCase = 49; continue; };
+case 36:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 30; continue; };
+            if (yych <= '9') { gotoCase = 68; continue; };
+            { gotoCase = 30; continue; };
+case 37:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '*') { gotoCase = 104; continue; };
+            { gotoCase = 49; continue; };
+case 38:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            switch (yych) {
+            case '!':
+            case '"':
+            case '$':
+            case '\'':
+            case '-':
+            case '/':
+            case '=':
+            case '@':
+            case 'A':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'E':
+            case 'F':
+            case 'G':
+            case 'I':
+            case 'J':
+            case 'K':
+            case 'L':
+            case 'M':
+            case 'N':
+            case 'O':
+            case 'P':
+            case 'Q':
+            case 'R':
+            case 'S':
+            case 'T':
+            case 'U':
+            case 'V':
+            case 'W':
+            case 'X':
+            case 'Y':
+            case 'Z':
+            case '[':
+            case ']':
+            case 'a':
+            case 'b':
+            case 'f':
+            case 'h':
+            case 'j':
+            case 'l':
+            case 'n':
+            case 'o':
+            case 'q':
+            case 'u':
+            case 'v':
+            case 'w':
+            case 'x':
+            case 'y':
+            case 'z':    { gotoCase = 48; continue; };
+            case '%':    { gotoCase = 67; continue; };
+            case '.':    { gotoCase = 65; continue; };
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':    { gotoCase = 50; continue; };
+            case 'H':    { gotoCase = 52; continue; };
+            case '_':    { gotoCase = 53; continue; };
+            case 'c':    { gotoCase = 54; continue; };
+            case 'd':    { gotoCase = 55; continue; };
+            case 'e':    { gotoCase = 56; continue; };
+            case 'g':    { gotoCase = 57; continue; };
+            case 'i':    { gotoCase = 58; continue; };
+            case 'k':    { gotoCase = 59; continue; };
+            case 'm':    { gotoCase = 60; continue; };
+            case 'p':    { gotoCase = 61; continue; };
+            case 'r':    { gotoCase = 62; continue; };
+            case 's':    { gotoCase = 63; continue; };
+            case 't':    { gotoCase = 64; continue; };
+            default:    { gotoCase = 39; continue; };
+            }
+case 39:
+            {
+                    if (this._isPropertyValue())
+                        this.tokenType = "css-number";
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+case 40:
+            ++cursor;
+            {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.PROPERTY)
+                        this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE;
+                    return cursor;
+                }
+case 42:
+            ++cursor;
+            {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.AT_RULE)
+                        this._condition.parseCondition = this._parseConditions.INITIAL;
+                    else
+                        this._condition.parseCondition = this._parseConditions.PROPERTY;
+                    return cursor;
+                }
+case 44:
+            ++cursor;
+            {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.AT_RULE)
+                        this._condition.parseCondition = this._parseConditions.INITIAL;
+                    else
+                        this._condition.parseCondition = this._parseConditions.PROPERTY;
+                    return cursor;
+                }
+case 46:
+            ++cursor;
+            {
+                    this.tokenType = null;
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+case 48:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 49:
+            if (yych <= '9') {
+                if (yych <= '&') {
+                    if (yych <= '"') {
+                        if (yych <= ' ') { gotoCase = 32; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych == '$') { gotoCase = 48; continue; };
+                        { gotoCase = 32; continue; };
+                    }
+                } else {
+                    if (yych <= ',') {
+                        if (yych <= '\'') { gotoCase = 48; continue; };
+                        { gotoCase = 32; continue; };
+                    } else {
+                        if (yych == '.') { gotoCase = 32; continue; };
+                        { gotoCase = 48; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '=') {
+                        if (yych <= '<') { gotoCase = 32; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '?') { gotoCase = 32; continue; };
+                        if (yych <= '[') { gotoCase = 48; continue; };
+                        { gotoCase = 32; continue; };
+                    }
+                } else {
+                    if (yych <= '_') {
+                        if (yych == '^') { gotoCase = 32; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '`') { gotoCase = 32; continue; };
+                        if (yych <= 'z') { gotoCase = 48; continue; };
+                        { gotoCase = 32; continue; };
+                    }
+                }
+            }
+case 50:
+            yyaccept = 1;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            switch (yych) {
+            case '!':
+            case '"':
+            case '$':
+            case '\'':
+            case '-':
+            case '/':
+            case '=':
+            case '@':
+            case 'A':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'E':
+            case 'F':
+            case 'G':
+            case 'I':
+            case 'J':
+            case 'K':
+            case 'L':
+            case 'M':
+            case 'N':
+            case 'O':
+            case 'P':
+            case 'Q':
+            case 'R':
+            case 'S':
+            case 'T':
+            case 'U':
+            case 'V':
+            case 'W':
+            case 'X':
+            case 'Y':
+            case 'Z':
+            case '[':
+            case ']':
+            case 'a':
+            case 'b':
+            case 'f':
+            case 'h':
+            case 'j':
+            case 'l':
+            case 'n':
+            case 'o':
+            case 'q':
+            case 'u':
+            case 'v':
+            case 'w':
+            case 'x':
+            case 'y':
+            case 'z':    { gotoCase = 48; continue; };
+            case '%':    { gotoCase = 67; continue; };
+            case '.':    { gotoCase = 65; continue; };
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':    { gotoCase = 50; continue; };
+            case 'H':    { gotoCase = 52; continue; };
+            case '_':    { gotoCase = 53; continue; };
+            case 'c':    { gotoCase = 54; continue; };
+            case 'd':    { gotoCase = 55; continue; };
+            case 'e':    { gotoCase = 56; continue; };
+            case 'g':    { gotoCase = 57; continue; };
+            case 'i':    { gotoCase = 58; continue; };
+            case 'k':    { gotoCase = 59; continue; };
+            case 'm':    { gotoCase = 60; continue; };
+            case 'p':    { gotoCase = 61; continue; };
+            case 'r':    { gotoCase = 62; continue; };
+            case 's':    { gotoCase = 63; continue; };
+            case 't':    { gotoCase = 64; continue; };
+            default:    { gotoCase = 39; continue; };
+            }
+case 52:
+            yych = this._charAt(++cursor);
+            if (yych == 'z') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 53:
+            yych = this._charAt(++cursor);
+            if (yych == '_') { gotoCase = 101; continue; };
+            { gotoCase = 49; continue; };
+case 54:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 55:
+            yych = this._charAt(++cursor);
+            if (yych == 'e') { gotoCase = 100; continue; };
+            { gotoCase = 49; continue; };
+case 56:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 63; continue; };
+            if (yych == 'x') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 57:
+            yych = this._charAt(++cursor);
+            if (yych == 'r') { gotoCase = 98; continue; };
+            { gotoCase = 49; continue; };
+case 58:
+            yych = this._charAt(++cursor);
+            if (yych == 'n') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 59:
+            yych = this._charAt(++cursor);
+            if (yych == 'H') { gotoCase = 97; continue; };
+            { gotoCase = 49; continue; };
+case 60:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 63; continue; };
+            if (yych == 's') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 61:
+            yych = this._charAt(++cursor);
+            if (yych <= 's') {
+                if (yych == 'c') { gotoCase = 63; continue; };
+                { gotoCase = 49; continue; };
+            } else {
+                if (yych <= 't') { gotoCase = 63; continue; };
+                if (yych == 'x') { gotoCase = 63; continue; };
+                { gotoCase = 49; continue; };
+            }
+case 62:
+            yych = this._charAt(++cursor);
+            if (yych == 'a') { gotoCase = 95; continue; };
+            if (yych == 'e') { gotoCase = 96; continue; };
+            { gotoCase = 49; continue; };
+case 63:
+            yych = this._charAt(++cursor);
+            if (yych <= '9') {
+                if (yych <= '&') {
+                    if (yych <= '"') {
+                        if (yych <= ' ') { gotoCase = 39; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych == '$') { gotoCase = 48; continue; };
+                        { gotoCase = 39; continue; };
+                    }
+                } else {
+                    if (yych <= ',') {
+                        if (yych <= '\'') { gotoCase = 48; continue; };
+                        { gotoCase = 39; continue; };
+                    } else {
+                        if (yych == '.') { gotoCase = 39; continue; };
+                        { gotoCase = 48; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '=') {
+                        if (yych <= '<') { gotoCase = 39; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '?') { gotoCase = 39; continue; };
+                        if (yych <= '[') { gotoCase = 48; continue; };
+                        { gotoCase = 39; continue; };
+                    }
+                } else {
+                    if (yych <= '_') {
+                        if (yych == '^') { gotoCase = 39; continue; };
+                        { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '`') { gotoCase = 39; continue; };
+                        if (yych <= 'z') { gotoCase = 48; continue; };
+                        { gotoCase = 39; continue; };
+                    }
+                }
+            }
+case 64:
+            yych = this._charAt(++cursor);
+            if (yych == 'u') { gotoCase = 93; continue; };
+            { gotoCase = 49; continue; };
+case 65:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 66; continue; };
+            if (yych <= '9') { gotoCase = 68; continue; };
+case 66:
+            cursor = YYMARKER;
+            if (yyaccept <= 0) {
+                { gotoCase = 32; continue; };
+            } else {
+                { gotoCase = 39; continue; };
+            }
+case 67:
+            yych = this._charAt(++cursor);
+            { gotoCase = 39; continue; };
+case 68:
+            yyaccept = 1;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'f') {
+                if (yych <= 'H') {
+                    if (yych <= '/') {
+                        if (yych == '%') { gotoCase = 67; continue; };
+                        { gotoCase = 39; continue; };
+                    } else {
+                        if (yych <= '9') { gotoCase = 68; continue; };
+                        if (yych <= 'G') { gotoCase = 39; continue; };
+                        { gotoCase = 80; continue; };
+                    }
+                } else {
+                    if (yych <= 'b') {
+                        if (yych == '_') { gotoCase = 72; continue; };
+                        { gotoCase = 39; continue; };
+                    } else {
+                        if (yych <= 'c') { gotoCase = 74; continue; };
+                        if (yych <= 'd') { gotoCase = 77; continue; };
+                        if (yych >= 'f') { gotoCase = 39; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'm') {
+                    if (yych <= 'i') {
+                        if (yych <= 'g') { gotoCase = 78; continue; };
+                        if (yych <= 'h') { gotoCase = 39; continue; };
+                        { gotoCase = 76; continue; };
+                    } else {
+                        if (yych == 'k') { gotoCase = 81; continue; };
+                        if (yych <= 'l') { gotoCase = 39; continue; };
+                        { gotoCase = 75; continue; };
+                    }
+                } else {
+                    if (yych <= 'q') {
+                        if (yych == 'p') { gotoCase = 73; continue; };
+                        { gotoCase = 39; continue; };
+                    } else {
+                        if (yych <= 'r') { gotoCase = 71; continue; };
+                        if (yych <= 's') { gotoCase = 67; continue; };
+                        if (yych <= 't') { gotoCase = 79; continue; };
+                        { gotoCase = 39; continue; };
+                    }
+                }
+            }
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 67; continue; };
+            if (yych == 'x') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 71:
+            yych = this._charAt(++cursor);
+            if (yych == 'a') { gotoCase = 91; continue; };
+            if (yych == 'e') { gotoCase = 92; continue; };
+            { gotoCase = 66; continue; };
+case 72:
+            yych = this._charAt(++cursor);
+            if (yych == '_') { gotoCase = 88; continue; };
+            { gotoCase = 66; continue; };
+case 73:
+            yych = this._charAt(++cursor);
+            if (yych <= 's') {
+                if (yych == 'c') { gotoCase = 67; continue; };
+                { gotoCase = 66; continue; };
+            } else {
+                if (yych <= 't') { gotoCase = 67; continue; };
+                if (yych == 'x') { gotoCase = 67; continue; };
+                { gotoCase = 66; continue; };
+            }
+case 74:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 75:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 67; continue; };
+            if (yych == 's') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 76:
+            yych = this._charAt(++cursor);
+            if (yych == 'n') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 77:
+            yych = this._charAt(++cursor);
+            if (yych == 'e') { gotoCase = 87; continue; };
+            { gotoCase = 66; continue; };
+case 78:
+            yych = this._charAt(++cursor);
+            if (yych == 'r') { gotoCase = 85; continue; };
+            { gotoCase = 66; continue; };
+case 79:
+            yych = this._charAt(++cursor);
+            if (yych == 'u') { gotoCase = 83; continue; };
+            { gotoCase = 66; continue; };
+case 80:
+            yych = this._charAt(++cursor);
+            if (yych == 'z') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 81:
+            yych = this._charAt(++cursor);
+            if (yych != 'H') { gotoCase = 66; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'z') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 83:
+            yych = this._charAt(++cursor);
+            if (yych != 'r') { gotoCase = 66; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'n') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 85:
+            yych = this._charAt(++cursor);
+            if (yych != 'a') { gotoCase = 66; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'd') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 87:
+            yych = this._charAt(++cursor);
+            if (yych == 'g') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 88:
+            yych = this._charAt(++cursor);
+            if (yych != 'q') { gotoCase = 66; continue; };
+            yych = this._charAt(++cursor);
+            if (yych != 'e') { gotoCase = 66; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 91:
+            yych = this._charAt(++cursor);
+            if (yych == 'd') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 92:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 67; continue; };
+            { gotoCase = 66; continue; };
+case 93:
+            yych = this._charAt(++cursor);
+            if (yych != 'r') { gotoCase = 49; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'n') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 95:
+            yych = this._charAt(++cursor);
+            if (yych == 'd') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 96:
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 97:
+            yych = this._charAt(++cursor);
+            if (yych == 'z') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 98:
+            yych = this._charAt(++cursor);
+            if (yych != 'a') { gotoCase = 49; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'd') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 100:
+            yych = this._charAt(++cursor);
+            if (yych == 'g') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 101:
+            yych = this._charAt(++cursor);
+            if (yych != 'q') { gotoCase = 49; continue; };
+            yych = this._charAt(++cursor);
+            if (yych != 'e') { gotoCase = 49; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == 'm') { gotoCase = 63; continue; };
+            { gotoCase = 49; continue; };
+case 104:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 108; continue; };
+                { gotoCase = 104; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 108; continue; };
+                if (yych != '*') { gotoCase = 104; continue; };
+            }
+case 106:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '*') { gotoCase = 106; continue; };
+            if (yych == '/') { gotoCase = 110; continue; };
+            { gotoCase = 104; continue; };
+case 108:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.COMMENT);
+            { this.tokenType = "css-comment"; return cursor; }
+case 110:
+            ++cursor;
+            { this.tokenType = "css-comment"; return cursor; }
+case 112:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '-') {
+                if (yych <= '"') {
+                    if (yych <= '\f') {
+                        if (yych == '\n') { gotoCase = 32; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '\r') { gotoCase = 32; continue; };
+                        if (yych <= ' ') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                } else {
+                    if (yych <= '&') {
+                        if (yych == '$') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '\'') { gotoCase = 114; continue; };
+                        if (yych <= ',') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '<') {
+                        if (yych <= '.') { gotoCase = 116; continue; };
+                        if (yych <= '9') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych <= '=') { gotoCase = 112; continue; };
+                        if (yych <= '?') { gotoCase = 116; continue; };
+                        { gotoCase = 112; continue; };
+                    }
+                } else {
+                    if (yych <= '^') {
+                        if (yych <= '\\') { gotoCase = 118; continue; };
+                        if (yych <= ']') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych == '`') { gotoCase = 116; continue; };
+                        if (yych <= 'z') { gotoCase = 112; continue; };
+                        { gotoCase = 116; continue; };
+                    }
+                }
+            }
+case 114:
+            ++cursor;
+            if ((yych = this._charAt(cursor)) <= '9') {
+                if (yych <= '&') {
+                    if (yych <= '"') {
+                        if (yych >= '!') { gotoCase = 48; continue; };
+                    } else {
+                        if (yych == '$') { gotoCase = 48; continue; };
+                    }
+                } else {
+                    if (yych <= ',') {
+                        if (yych <= '\'') { gotoCase = 48; continue; };
+                    } else {
+                        if (yych != '.') { gotoCase = 48; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '=') {
+                        if (yych >= '=') { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '?') { gotoCase = 115; continue; };
+                        if (yych <= '[') { gotoCase = 48; continue; };
+                    }
+                } else {
+                    if (yych <= '_') {
+                        if (yych != '^') { gotoCase = 48; continue; };
+                    } else {
+                        if (yych <= '`') { gotoCase = 115; continue; };
+                        if (yych <= 'z') { gotoCase = 48; continue; };
+                    }
+                }
+            }
+case 115:
+            { return this._stringToken(cursor, true); }
+case 116:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 66; continue; };
+                if (yych <= '\f') { gotoCase = 116; continue; };
+                { gotoCase = 66; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 116; continue; };
+                    { gotoCase = 121; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 116; continue; };
+                }
+            }
+case 118:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 66; continue; };
+                    } else {
+                        if (yych != '\r') { gotoCase = 66; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 116; continue; };
+                        if (yych <= '&') { gotoCase = 66; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 116; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 116; continue; };
+                        if (yych <= 'e') { gotoCase = 66; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 116; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 66; continue; };
+                        { gotoCase = 116; continue; };
+                    } else {
+                        if (yych == 'v') { gotoCase = 116; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                }
+            }
+            ++cursor;
+            this.setLexCondition(this._lexConditions.SSTRING);
+            { return this._stringToken(cursor); }
+case 121:
+            yych = this._charAt(++cursor);
+            { gotoCase = 115; continue; };
+case 122:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '-') {
+                if (yych <= '!') {
+                    if (yych <= '\f') {
+                        if (yych == '\n') { gotoCase = 32; continue; };
+                    } else {
+                        if (yych <= '\r') { gotoCase = 32; continue; };
+                        if (yych >= '!') { gotoCase = 122; continue; };
+                    }
+                } else {
+                    if (yych <= '$') {
+                        if (yych <= '"') { gotoCase = 114; continue; };
+                        if (yych >= '$') { gotoCase = 122; continue; };
+                    } else {
+                        if (yych == '\'') { gotoCase = 122; continue; };
+                        if (yych >= '-') { gotoCase = 122; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '<') {
+                        if (yych <= '.') { gotoCase = 124; continue; };
+                        if (yych <= '9') { gotoCase = 122; continue; };
+                    } else {
+                        if (yych <= '=') { gotoCase = 122; continue; };
+                        if (yych >= '@') { gotoCase = 122; continue; };
+                    }
+                } else {
+                    if (yych <= '^') {
+                        if (yych <= '\\') { gotoCase = 126; continue; };
+                        if (yych <= ']') { gotoCase = 122; continue; };
+                    } else {
+                        if (yych == '`') { gotoCase = 124; continue; };
+                        if (yych <= 'z') { gotoCase = 122; continue; };
+                    }
+                }
+            }
+case 124:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 66; continue; };
+                if (yych <= '\f') { gotoCase = 124; continue; };
+                { gotoCase = 66; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 124; continue; };
+                    { gotoCase = 121; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 124; continue; };
+                }
+            }
+case 126:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 66; continue; };
+                    } else {
+                        if (yych != '\r') { gotoCase = 66; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 124; continue; };
+                        if (yych <= '&') { gotoCase = 66; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 124; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 124; continue; };
+                        if (yych <= 'e') { gotoCase = 66; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 124; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 66; continue; };
+                        { gotoCase = 124; continue; };
+                    } else {
+                        if (yych == 'v') { gotoCase = 124; continue; };
+                        { gotoCase = 66; continue; };
+                    }
+                }
+            }
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DSTRING);
+            { return this._stringToken(cursor); }
+/* *********************************** */
+case this.case_SSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 133; continue; };
+                if (yych <= '\f') { gotoCase = 132; continue; };
+                { gotoCase = 133; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 132; continue; };
+                    { gotoCase = 135; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 137; continue; };
+                    { gotoCase = 132; continue; };
+                }
+            }
+case 131:
+            { return this._stringToken(cursor); }
+case 132:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 139; continue; };
+case 133:
+            ++cursor;
+case 134:
+            { this.tokenType = null; return cursor; }
+case 135:
+            ++cursor;
+case 136:
+            this.setLexCondition(this._lexConditions.INITIAL);
+            { return this._stringToken(cursor, true); }
+case 137:
+            yych = this._charAt(++cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 138; continue; };
+                    if (yych <= '&') { gotoCase = 134; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 134; continue; };
+                    } else {
+                        if (yych != 'b') { gotoCase = 134; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych >= 'g') { gotoCase = 134; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 138; continue; };
+                        if (yych <= 'q') { gotoCase = 134; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 134; continue; };
+                    } else {
+                        if (yych != 'v') { gotoCase = 134; continue; };
+                    }
+                }
+            }
+case 138:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 139:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 131; continue; };
+                if (yych <= '\f') { gotoCase = 138; continue; };
+                { gotoCase = 131; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 138; continue; };
+                    { gotoCase = 142; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 138; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 138; continue; };
+                    if (yych >= '\'') { gotoCase = 138; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych >= '\\') { gotoCase = 138; continue; };
+                    } else {
+                        if (yych == 'b') { gotoCase = 138; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych <= 'f') { gotoCase = 138; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 138; continue; };
+                        if (yych >= 'r') { gotoCase = 138; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych >= 't') { gotoCase = 138; continue; };
+                    } else {
+                        if (yych == 'v') { gotoCase = 138; continue; };
+                    }
+                }
+            }
+            cursor = YYMARKER;
+            { gotoCase = 131; continue; };
+case 142:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 136; continue; };
+        }
+
+        }
+    }
+}
+
+WebInspector.SourceCSSTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.re2js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.re2js
new file mode 100644
index 0000000..1b84b43
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceCSSTokenizer.re2js
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceCSSTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|goto case \([^;]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: var yych|'
+
+WebInspector.SourceCSSTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    this._propertyKeywords = WebInspector.cssNameCompletions.keySet();
+
+    this._valueKeywords = [
+        "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll",
+        "alternate", "always","amharic", "amharic-abegede", "antialiased", "appworkspace", "aqua", "arabic-indic", "armenian", "asterisks",
+        "auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "black", "blink",
+        "block", "block-axis", "blue", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button",
+        "button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator",
+        "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic",
+        "clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu",
+        "continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default",
+        "default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document",
+        "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element",
+        "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez",
+        "ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et",
+        "ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et",
+        "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded",
+        "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "fuchsia", "geometricPrecision",
+        "georgian", "gray", "graytext", "green", "grey", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help",
+        "hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
+        "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline",
+        "inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana",
+        "katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "lime", "line-through", "linear", "lines",
+        "list-button", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek",
+        "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "maroon", "match", "media-controls-background",
+        "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button",
+        "media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display",
+        "media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button",
+        "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple",
+        "myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none",
+        "normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "olive", "open-quote", "optimizeLegibility",
+        "optimizeSpeed", "orange", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused",
+        "persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "purple",
+        "push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "red", "relative", "repeat", "repeat-x",
+        "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif",
+        "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
+        "searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "silver", "single",
+        "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
+        "small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over",
+        "space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super",
+        "sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group",
+        "table-row", "table-row-group", "teal", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin",
+        "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede",
+        "tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian",
+        "upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible",
+        "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext",
+        "x-large", "x-small", "xor", "xx-large", "xx-small", "yellow", "-wap-marquee", "-webkit-activelink", "-webkit-auto", "-webkit-baseline-middle",
+        "-webkit-body", "-webkit-box", "-webkit-center", "-webkit-control", "-webkit-focus-ring-color", "-webkit-grab", "-webkit-grabbing",
+        "-webkit-gradient", "-webkit-inline-box", "-webkit-left", "-webkit-link", "-webkit-marquee", "-webkit-mini-control", "-webkit-nowrap", "-webkit-right",
+        "-webkit-small-control", "-webkit-text", "-webkit-xxx-large", "-webkit-zoom-in", "-webkit-zoom-out",
+    ].keySet();
+
+    this._mediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet();
+
+    this._lexConditions = {
+        INITIAL: 0,
+        COMMENT: 1,
+        DSTRING: 2,
+        SSTRING: 3
+    };
+
+    this._parseConditions = {
+        INITIAL: 0,
+        PROPERTY: 1,
+        PROPERTY_VALUE: 2,
+        AT_RULE: 3
+    };
+
+    this.case_INITIAL = 1000;
+    this.case_COMMENT = 1002;
+    this.case_DSTRING = 1003;
+    this.case_SSTRING = 1004;
+
+    this.initialCondition = { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }
+}
+
+WebInspector.SourceCSSTokenizer.prototype = {
+    _stringToken: function(cursor, stringEnds)
+    {
+        if (this._isPropertyValue())
+            this.tokenType = "css-string";
+        else
+            this.tokenType = null;
+        return cursor;
+    },
+
+    _isPropertyValue: function()
+    {
+        return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE;
+    },
+
+    nextToken: function(cursor)
+    {
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            /*!re2c
+                re2c:define:YYCTYPE  = "var";
+                re2c:define:YYCURSOR = cursor;
+                re2c:define:YYGETCONDITION = "this.getLexCondition";
+                re2c:define:YYSETCONDITION = "this.setLexCondition";
+                re2c:condprefix = "case this.case_";
+                re2c:condenumprefix = "this._lexConditions.";
+                re2c:yyfill:enable = 0;
+                re2c:labelprefix = "case ";
+                re2c:indent:top = 2;
+                re2c:indent:string = "    ";
+
+                CommentContent = ([^*\r\n] | ("*"+[^/*]))*;
+                Comment = "/*" CommentContent "*"+ "/";
+                CommentStart = "/*" CommentContent [\r\n];
+                CommentEnd = CommentContent "*"+ "/";
+
+                OpenCurlyBracket = "{";
+                CloseCurlyBracket = "}";
+
+                Colon = ":";
+                Semicolon = ";";
+
+                NumericLiteral = "-"? ([0-9]+ | [0-9]* "." [0-9]+)  ("em" | "rem" | "__qem" | "ex" | "px" | "cm" | 
+                    "mm" | "in" | "pt" | "pc" | "deg" | "rad" | "grad" | "turn" | "ms" | "s" | "Hz" | "kHz" | "%")?;
+
+                Identifier = [@!_\-$0-9a-zA-Z\[\]='"/]+;
+
+                DoubleStringContent = ([^\r\n\"\\] | "\\" ['"\\bfnrtv])*;
+                SingleStringContent = ([^\r\n\'\\] | "\\" ['"\\bfnrtv])*;
+                StringLiteral = "\"" DoubleStringContent "\"" | "'" SingleStringContent "'";
+                DoubleStringStart = "\"" DoubleStringContent "\\" [\r\n];
+                DoubleStringEnd = DoubleStringContent "\"";
+                SingleStringStart = "'" SingleStringContent "\\" [\r\n];
+                SingleStringEnd = SingleStringContent "'";
+
+                <INITIAL> Comment { this.tokenType = "css-comment"; return cursor; }
+                <INITIAL> CommentStart => COMMENT { this.tokenType = "css-comment"; return cursor; }
+                <COMMENT> CommentContent => COMMENT { this.tokenType = "css-comment"; return cursor; }
+                <COMMENT> CommentEnd => INITIAL { this.tokenType = "css-comment"; return cursor; }
+
+                <INITIAL> StringLiteral { return this._stringToken(cursor, true); }
+                <INITIAL> DoubleStringStart => DSTRING { return this._stringToken(cursor); }
+                <DSTRING> DoubleStringContent => DSTRING { return this._stringToken(cursor); }
+                <DSTRING> DoubleStringEnd => INITIAL { return this._stringToken(cursor, true); }
+                <INITIAL> SingleStringStart => SSTRING { return this._stringToken(cursor); }
+                <SSTRING> SingleStringContent => SSTRING { return this._stringToken(cursor); }
+                <SSTRING> SingleStringEnd => INITIAL { return this._stringToken(cursor, true); }
+
+                <INITIAL> OpenCurlyBracket
+                {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.AT_RULE)
+                        this._condition.parseCondition = this._parseConditions.INITIAL;
+                    else
+                        this._condition.parseCondition = this._parseConditions.PROPERTY;
+                    return cursor;
+                }
+
+                <INITIAL> CloseCurlyBracket
+                {
+                    this.tokenType = null;
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+
+                <INITIAL> Colon
+                {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.PROPERTY)
+                        this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE;
+                    return cursor;
+                }
+
+                <INITIAL> Semicolon
+                {
+                    this.tokenType = null;
+                    if (this._condition.parseCondition === this._parseConditions.AT_RULE)
+                        this._condition.parseCondition = this._parseConditions.INITIAL;
+                    else
+                        this._condition.parseCondition = this._parseConditions.PROPERTY;
+                    return cursor;
+                }
+
+                <INITIAL> NumericLiteral
+                {
+                    if (this._isPropertyValue())
+                        this.tokenType = "css-number";
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+
+                <INITIAL> Identifier
+                {
+                    var token = this._line.substring(cursorOnEnter, cursor);
+                    if (this._condition.parseCondition === this._parseConditions.INITIAL) {
+                        if (token === "@import" || token === "@media") {
+                            this.tokenType = "css-at-rule";
+                            this._condition.parseCondition = this._parseConditions.AT_RULE;
+                        } else if (token.indexOf("@") === 0)
+                            this.tokenType = "css-at-rule";
+                        else
+                            this.tokenType = "css-selector";
+                    }
+                    else if (this._condition.parseCondition === this._parseConditions.AT_RULE && token in this._mediaTypes)
+                        this.tokenType = "css-keyword";
+                    else if (this._condition.parseCondition === this._parseConditions.PROPERTY && token in this._propertyKeywords)
+                        this.tokenType = "css-property";
+                    else if (this._isPropertyValue() && token in this._valueKeywords)
+                        this.tokenType = "css-keyword";
+                    else if (token === "!important")
+                        this.tokenType = "css-important";
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+                <*> [^] { this.tokenType = null; return cursor; }
+            */
+        }
+    }
+}
+
+WebInspector.SourceCSSTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrame.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrame.js
new file mode 100644
index 0000000..6b4b3b3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrame.js
@@ -0,0 +1,935 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceFrame = function(contentProvider, url, isScript)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("script-view");
+
+    this._contentProvider = contentProvider;
+    this._url = url;
+    this._isScript = isScript;
+
+    this._textModel = new WebInspector.TextEditorModel();
+    this._textModel.replaceTabsWithSpaces = true;
+
+    this._currentSearchResultIndex = -1;
+    this._searchResults = [];
+
+    this._messages = [];
+    this._rowMessages = {};
+    this._messageBubbles = {};
+
+    this._popoverObjectGroup = "popover";
+}
+
+WebInspector.SourceFrame.prototype = {
+
+    show: function(parentElement)
+    {
+        WebInspector.View.prototype.show.call(this, parentElement);
+
+        if (!this._contentRequested) {
+            this._contentRequested = true;
+            this._contentProvider.requestContent(this._createTextViewer.bind(this));
+        }
+
+        if (this._textViewer) {
+            if (this._scrollTop)
+                this._textViewer.scrollTop = this._scrollTop;
+            if (this._scrollLeft)
+                this._textViewer.scrollLeft = this._scrollLeft;
+            this._textViewer.resize();
+        }
+    },
+
+    hide: function()
+    {
+        if (this._textViewer) {
+            this._scrollTop = this._textViewer.scrollTop;
+            this._scrollLeft = this._textViewer.scrollLeft;
+            this._textViewer.freeCachedElements();
+        }
+
+        WebInspector.View.prototype.hide.call(this);
+
+        this._hidePopup();
+        this._clearLineHighlight();
+    },
+
+    hasContent: function()
+    {
+        return true;
+    },
+
+    markDiff: function(diffData)
+    {
+        if (this._diffLines && this._textViewer)
+            this._removeDiffDecorations();
+
+        this._diffLines = diffData;
+        if (this._textViewer)
+            this._updateDiffDecorations();
+    },
+
+    revealLine: function(lineNumber)
+    {
+        if (this._textViewer)
+            this._textViewer.revealLine(lineNumber - 1, 0);
+        else
+            this._lineNumberToReveal = lineNumber;
+    },
+
+    addMessage: function(msg)
+    {
+        // Don't add the message if there is no message or valid line or if the msg isn't an error or warning.
+        if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
+            return;
+        this._messages.push(msg);
+        if (this._textViewer)
+            this._addMessageToSource(msg);
+    },
+
+    clearMessages: function()
+    {
+        for (var line in this._messageBubbles) {
+            var bubble = this._messageBubbles[line];
+            bubble.parentNode.removeChild(bubble);
+        }
+
+        this._messages = [];
+        this._rowMessages = {};
+        this._messageBubbles = {};
+        if (this._textViewer)
+            this._textViewer.resize();
+    },
+
+    sizeToFitContentHeight: function()
+    {
+        if (this._textViewer)
+            this._textViewer.revalidateDecorationsAndPaint();
+    },
+
+    get textModel()
+    {
+        return this._textModel;
+    },
+
+    get scrollTop()
+    {
+        return this._textViewer ? this._textViewer.scrollTop : this._scrollTop;
+    },
+
+    set scrollTop(scrollTop)
+    {
+        this._scrollTop = scrollTop;
+        if (this._textViewer)
+            this._textViewer.scrollTop = scrollTop;
+    },
+
+    highlightLine: function(line)
+    {
+        if (this._textViewer)
+            this._textViewer.highlightLine(line - 1);
+        else
+            this._lineToHighlight = line;
+    },
+
+    _clearLineHighlight: function()
+    {
+        if (this._textViewer)
+            this._textViewer.clearLineHighlight();
+        else
+            delete this._lineToHighlight;
+    },
+
+    _createTextViewer: function(mimeType, content)
+    {
+        this._content = content;
+        this._textModel.setText(null, content.text);
+
+        this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url);
+        var element = this._textViewer.element;
+        element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
+        element.addEventListener("mousedown", this._mouseDown.bind(this), true);
+        element.addEventListener("mousemove", this._mouseMove.bind(this), true);
+        element.addEventListener("scroll", this._scroll.bind(this), true);
+        element.addEventListener("dblclick", this._doubleClick.bind(this), true);
+        this.element.appendChild(element);
+
+        this._textViewer.beginUpdates();
+
+        this._textViewer.mimeType = mimeType;
+        this._setTextViewerDecorations();
+
+        if (this._lineNumberToReveal) {
+            this.revealLine(this._lineNumberToReveal);
+            delete this._lineNumberToReveal;
+        }
+
+        if (this._lineToHighlight) {
+            this.highlightLine(this._lineToHighlight);
+            delete this._lineToHighlight;
+        }
+
+        if (this._delayedFindSearchMatches) {
+            this._delayedFindSearchMatches();
+            delete this._delayedFindSearchMatches;
+        }
+
+        this._textViewer.endUpdates();
+
+        WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
+        WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+        WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+    },
+
+    _setTextViewerDecorations: function()
+    {
+        this._rowMessages = {};
+        this._messageBubbles = {};
+
+        this._textViewer.beginUpdates();
+
+        this._addExistingMessagesToSource();
+        this._updateDiffDecorations();
+
+        if (this._executionLocation)
+            this._setExecutionLocation();
+
+        this._breakpointIdToTextViewerLineNumber = {};
+        this._textViewerLineNumberToBreakpointId = {};
+        var breakpoints = WebInspector.debuggerModel.breakpoints;
+        for (var id in breakpoints)
+            this._breakpointAdded({ data: breakpoints[id] });
+
+        this._textViewer.resize();
+
+        this._textViewer.endUpdates();
+    },
+
+    _shouldDisplayBreakpoint: function(breakpoint)
+    {
+        if (this._url)
+            return this._url === breakpoint.url;
+        var scripts = this._content.scriptRanges;
+        for (var i = 0; i < scripts.length; ++i) {
+            if (breakpoint.sourceID === scripts[i].sourceID)
+                return true;
+        }
+        return false;
+    },
+
+    performSearch: function(query, callback)
+    {
+        // Call searchCanceled since it will reset everything we need before doing a new search.
+        this.searchCanceled();
+
+        function doFindSearchMatches(query)
+        {
+            this._currentSearchResultIndex = -1;
+            this._searchResults = [];
+
+            // First do case-insensitive search.
+            var regexObject = createSearchRegex(query);
+            this._collectRegexMatches(regexObject, this._searchResults);
+
+            // Then try regex search if user knows the / / hint.
+            try {
+                if (/^\/.*\/$/.test(query))
+                    this._collectRegexMatches(new RegExp(query.substring(1, query.length - 1)), this._searchResults);
+            } catch (e) {
+                // Silent catch.
+            }
+
+            callback(this, this._searchResults.length);
+        }
+
+        if (this._textViewer)
+            doFindSearchMatches.call(this, query);
+        else
+            this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query);
+
+    },
+
+    searchCanceled: function()
+    {
+        delete this._delayedFindSearchMatches;
+        if (!this._textViewer)
+            return;
+
+        this._currentSearchResultIndex = -1;
+        this._searchResults = [];
+        this._textViewer.markAndRevealRange(null);
+    },
+
+    jumpToFirstSearchResult: function()
+    {
+        this._jumpToSearchResult(0);
+    },
+
+    jumpToLastSearchResult: function()
+    {
+        this._jumpToSearchResult(this._searchResults.length - 1);
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        this._jumpToSearchResult(this._currentSearchResultIndex + 1);
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        this._jumpToSearchResult(this._currentSearchResultIndex - 1);
+    },
+
+    showingFirstSearchResult: function()
+    {
+        return this._searchResults.length &&  this._currentSearchResultIndex === 0;
+    },
+
+    showingLastSearchResult: function()
+    {
+        return this._searchResults.length && this._currentSearchResultIndex === (this._searchResults.length - 1);
+    },
+
+    _jumpToSearchResult: function(index)
+    {
+        if (!this._textViewer || !this._searchResults.length)
+            return;
+        this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
+        this._textViewer.markAndRevealRange(this._searchResults[this._currentSearchResultIndex]);
+    },
+
+    _collectRegexMatches: function(regexObject, ranges)
+    {
+        for (var i = 0; i < this._textModel.linesCount; ++i) {
+            var line = this._textModel.line(i);
+            var offset = 0;
+            do {
+                var match = regexObject.exec(line);
+                if (match) {
+                    ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length));
+                    offset += match.index + 1;
+                    line = line.substring(match.index + 1);
+                }
+            } while (match)
+        }
+        return ranges;
+    },
+
+    _incrementMessageRepeatCount: function(msg, repeatDelta)
+    {
+        if (!msg._resourceMessageLineElement)
+            return;
+
+        if (!msg._resourceMessageRepeatCountElement) {
+            var repeatedElement = document.createElement("span");
+            msg._resourceMessageLineElement.appendChild(repeatedElement);
+            msg._resourceMessageRepeatCountElement = repeatedElement;
+        }
+
+        msg.repeatCount += repeatDelta;
+        msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount);
+    },
+
+    setExecutionLocation: function(lineNumber, columnNumber)
+    {
+        this._executionLocation = { lineNumber: lineNumber, columnNumber: columnNumber };
+        if (this._textViewer)
+            this._setExecutionLocation();
+    },
+
+    clearExecutionLocation: function()
+    {
+        if (this._textViewer) {
+            var textViewerLineNumber = this._content.actualLocationToSourceFrameLineNumber(this._executionLocation.lineNumber, this._executionLocation.columnNumber);
+            this._textViewer.removeDecoration(textViewerLineNumber, "webkit-execution-line");
+        }
+        delete this._executionLocation;
+    },
+
+    _setExecutionLocation: function()
+    {
+        var textViewerLineNumber = this._content.actualLocationToSourceFrameLineNumber(this._executionLocation.lineNumber, this._executionLocation.columnNumber);
+        this._textViewer.addDecoration(textViewerLineNumber, "webkit-execution-line");
+    },
+
+    _updateDiffDecorations: function()
+    {
+        if (!this._diffLines)
+            return;
+
+        function addDecorations(textViewer, lines, className)
+        {
+            for (var i = 0; i < lines.length; ++i)
+                textViewer.addDecoration(lines[i], className);
+        }
+        addDecorations(this._textViewer, this._diffLines.added, "webkit-added-line");
+        addDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line");
+        addDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line");
+    },
+
+    _removeDiffDecorations: function()
+    {
+        function removeDecorations(textViewer, lines, className)
+        {
+            for (var i = 0; i < lines.length; ++i)
+                textViewer.removeDecoration(lines[i], className);
+        }
+        removeDecorations(this._textViewer, this._diffLines.added, "webkit-added-line");
+        removeDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line");
+        removeDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line");
+    },
+
+    _addExistingMessagesToSource: function()
+    {
+        var length = this._messages.length;
+        for (var i = 0; i < length; ++i)
+            this._addMessageToSource(this._messages[i]);
+    },
+
+    _addMessageToSource: function(msg)
+    {
+        if (msg.line > this._textModel.linesCount)
+            return;
+
+        var messageBubbleElement = this._messageBubbles[msg.line];
+        if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
+            messageBubbleElement = document.createElement("div");
+            messageBubbleElement.className = "webkit-html-message-bubble";
+            this._messageBubbles[msg.line] = messageBubbleElement;
+            this._textViewer.addDecoration(msg.line - 1, messageBubbleElement);
+        }
+
+        var rowMessages = this._rowMessages[msg.line];
+        if (!rowMessages) {
+            rowMessages = [];
+            this._rowMessages[msg.line] = rowMessages;
+        }
+
+        for (var i = 0; i < rowMessages.length; ++i) {
+            if (rowMessages[i].isEqual(msg)) {
+                this._incrementMessageRepeatCount(rowMessages[i], msg.repeatDelta);
+                return;
+            }
+        }
+
+        rowMessages.push(msg);
+
+        var imageURL;
+        switch (msg.level) {
+            case WebInspector.ConsoleMessage.MessageLevel.Error:
+                messageBubbleElement.addStyleClass("webkit-html-error-message");
+                imageURL = "Images/errorIcon.png";
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Warning:
+                messageBubbleElement.addStyleClass("webkit-html-warning-message");
+                imageURL = "Images/warningIcon.png";
+                break;
+        }
+
+        var messageLineElement = document.createElement("div");
+        messageLineElement.className = "webkit-html-message-line";
+        messageBubbleElement.appendChild(messageLineElement);
+
+        // Create the image element in the Inspector's document so we can use relative image URLs.
+        var image = document.createElement("img");
+        image.src = imageURL;
+        image.className = "webkit-html-message-icon";
+        messageLineElement.appendChild(image);
+        messageLineElement.appendChild(document.createTextNode(msg.message));
+
+        msg._resourceMessageLineElement = messageLineElement;
+    },
+
+    _breakpointAdded: function(event)
+    {
+        var breakpoint = event.data;
+
+        if (!this._shouldDisplayBreakpoint(breakpoint))
+            return;
+
+        var resolved = breakpoint.locations.length;
+        var location = resolved ? breakpoint.locations[0] : breakpoint;
+
+        var textViewerLineNumber = this._content.actualLocationToSourceFrameLineNumber(location.lineNumber, location.columnNumber);
+        if (textViewerLineNumber >= this._textModel.linesCount)
+            return;
+
+        var existingBreakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
+        if (existingBreakpointId) {
+            WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+            return;
+        }
+
+        this._breakpointIdToTextViewerLineNumber[breakpoint.id] = textViewerLineNumber;
+        this._textViewerLineNumberToBreakpointId[textViewerLineNumber] = breakpoint.id;
+        this._setBreakpointDecoration(textViewerLineNumber, resolved, breakpoint.enabled, !!breakpoint.condition);
+    },
+
+    _breakpointRemoved: function(event)
+    {
+        var breakpointId = event.data;
+
+        var textViewerLineNumber = this._breakpointIdToTextViewerLineNumber[breakpointId];
+        if (textViewerLineNumber === undefined)
+            return;
+
+        delete this._breakpointIdToTextViewerLineNumber[breakpointId];
+        delete this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
+        this._removeBreakpointDecoration(textViewerLineNumber);
+    },
+
+    _breakpointResolved: function(event)
+    {
+        var breakpoint = event.data;
+        this._breakpointRemoved({ data: breakpoint.id });
+        this._breakpointAdded({ data: breakpoint });
+    },
+
+    _setBreakpointDecoration: function(lineNumber, resolved, enabled, hasCondition)
+    {
+        this._textViewer.beginUpdates();
+        this._textViewer.addDecoration(lineNumber, "webkit-breakpoint");
+        if (!enabled)
+            this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
+        if (hasCondition)
+            this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional");
+        this._textViewer.endUpdates();
+    },
+
+    _removeBreakpointDecoration: function(lineNumber)
+    {
+        this._textViewer.beginUpdates();
+        this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint");
+        this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled");
+        this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional");
+        this._textViewer.endUpdates();
+    },
+
+    _contextMenu: function(event)
+    {
+        if (!WebInspector.panels.scripts)
+            return;
+
+        var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
+        if (!target)
+            return;
+        var textViewerLineNumber = target.lineNumber;
+
+        var contextMenu = new WebInspector.ContextMenu();
+
+        contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._continueToLine.bind(this, textViewerLineNumber));
+
+        var breakpoint = this._findBreakpoint(textViewerLineNumber);
+        if (!breakpoint) {
+            // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
+            contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._setBreakpoint.bind(this, textViewerLineNumber, "", true));
+
+            function addConditionalBreakpoint()
+            {
+                this._setBreakpointDecoration(textViewerLineNumber, true, true, true);
+                function didEditBreakpointCondition(committed, condition)
+                {
+                    this._removeBreakpointDecoration(textViewerLineNumber);
+                    if (committed)
+                        this._setBreakpoint(textViewerLineNumber, condition, true);
+                }
+                this._editBreakpointCondition(textViewerLineNumber, "", didEditBreakpointCondition.bind(this));
+            }
+            contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this));
+        } else {
+            // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
+            function removeBreakpoint()
+            {
+                WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+            }
+            contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint);
+            function editBreakpointCondition()
+            {
+                function didEditBreakpointCondition(committed, condition)
+                {
+                    if (committed)
+                        WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, condition, breakpoint.enabled);
+                }
+                this._editBreakpointCondition(textViewerLineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
+            }
+            contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint…"), editBreakpointCondition.bind(this));
+            function setBreakpointEnabled(enabled)
+            {
+                WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, enabled);
+            }
+            if (breakpoint.enabled)
+                contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), setBreakpointEnabled.bind(this, false));
+            else
+                contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), setBreakpointEnabled.bind(this, true));
+        }
+        contextMenu.show(event);
+    },
+
+    _scroll: function(event)
+    {
+        this._hidePopup();
+    },
+
+    _mouseDown: function(event)
+    {
+        this._resetHoverTimer();
+        this._hidePopup();
+        if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey)
+            return;
+        var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
+        if (!target)
+            return;
+        var textViewerLineNumber = target.lineNumber;
+
+        var breakpoint = this._findBreakpoint(textViewerLineNumber);
+        if (breakpoint) {
+            if (event.shiftKey)
+                WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, !breakpoint.enabled);
+            else
+                WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+        } else
+            this._setBreakpoint(textViewerLineNumber, "", true);
+        event.preventDefault();
+    },
+
+    _mouseMove: function(event)
+    {
+        // Pretend that nothing has happened.
+        if (this._hoverElement === event.target || event.target.hasStyleClass("source-frame-eval-expression"))
+            return;
+
+        this._resetHoverTimer();
+        // User has 500ms to reach the popup.
+        if (this._popup) {
+            var self = this;
+            function doHide()
+            {
+                self._hidePopup();
+                delete self._hidePopupTimer;
+            }
+            if (!("_hidePopupTimer" in this))
+                this._hidePopupTimer = setTimeout(doHide, 500);
+        }
+
+        this._hoverElement = event.target;
+
+        // Now that cleanup routines are set up above, leave this in case we are not on a break.
+        if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+            return;
+
+        // We are interested in identifiers and "this" keyword.
+        if (this._hoverElement.hasStyleClass("webkit-javascript-keyword")) {
+            if (this._hoverElement.textContent !== "this")
+                return;
+        } else if (!this._hoverElement.hasStyleClass("webkit-javascript-ident"))
+            return;
+
+        const toolTipDelay = this._popup ? 600 : 1000;
+        this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay);
+    },
+
+    _resetHoverTimer: function()
+    {
+        if (this._hoverTimer) {
+            clearTimeout(this._hoverTimer);
+            delete this._hoverTimer;
+        }
+    },
+
+    _hidePopup: function()
+    {
+        if (!this._popup)
+            return;
+
+        // Replace higlight element with its contents inplace.
+        var parentElement = this._popup.highlightElement.parentElement;
+        var child = this._popup.highlightElement.firstChild;
+        while (child) {
+            var nextSibling = child.nextSibling;
+            parentElement.insertBefore(child, this._popup.highlightElement);
+            child = nextSibling;
+        }
+        parentElement.removeChild(this._popup.highlightElement);
+
+        this._popup.hide();
+        delete this._popup;
+        InspectorBackend.releaseWrapperObjectGroup(0, this._popoverObjectGroup);
+    },
+
+    _mouseHover: function(element)
+    {
+        delete this._hoverTimer;
+
+        if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+            return;
+
+        var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content");
+        if (!lineRow)
+            return;
+
+        // Collect tokens belonging to evaluated exression.
+        var tokens = [ element ];
+        var token = element.previousSibling;
+        while (token && (token.className === "webkit-javascript-ident" || token.className === "webkit-javascript-keyword" || token.textContent.trim() === ".")) {
+            tokens.push(token);
+            token = token.previousSibling;
+        }
+        tokens.reverse();
+
+        // Wrap them with highlight element.
+        var parentElement = element.parentElement;
+        var nextElement = element.nextSibling;
+        var container = document.createElement("span");
+        for (var i = 0; i < tokens.length; ++i)
+            container.appendChild(tokens[i]);
+        parentElement.insertBefore(container, nextElement);
+        this._showPopup(container);
+    },
+
+    _showPopup: function(element)
+    {
+        function killHidePopupTimer()
+        {
+            if (this._hidePopupTimer) {
+                clearTimeout(this._hidePopupTimer);
+                delete this._hidePopupTimer;
+
+                // We know that we reached the popup, but we might have moved over other elements.
+                // Discard pending command.
+                this._resetHoverTimer();
+            }
+        }
+
+        function showObjectPopup(result)
+        {
+            if (!WebInspector.panels.scripts.paused)
+                return;
+
+            var popupContentElement = null;
+            if (result.type !== "object" && result.type !== "node" && result.type !== "array") {
+                popupContentElement = document.createElement("span");
+                popupContentElement.className = "monospace console-formatted-" + result.type;
+                popupContentElement.style.whiteSpace = "pre";
+                popupContentElement.textContent = result.description;
+                if (result.type === "string")
+                    popupContentElement.textContent = "\"" + popupContentElement.textContent + "\"";
+                this._popup = new WebInspector.Popover(popupContentElement);
+                this._popup.show(element);
+            } else {
+                var popupContentElement = document.createElement("div");
+
+                var titleElement = document.createElement("div");
+                titleElement.className = "source-frame-popover-title monospace";
+                titleElement.textContent = result.description;
+                popupContentElement.appendChild(titleElement);
+
+                var section = new WebInspector.ObjectPropertiesSection(result, "", null, false);
+                section.expanded = true;
+                section.element.addStyleClass("source-frame-popover-tree");
+                section.headerElement.addStyleClass("hidden");
+                popupContentElement.appendChild(section.element);
+
+                this._popup = new WebInspector.Popover(popupContentElement);
+                const popupWidth = 300;
+                const popupHeight = 250;
+                this._popup.show(element, popupWidth, popupHeight);
+            }
+            this._popup.highlightElement = element;
+            this._popup.highlightElement.addStyleClass("source-frame-eval-expression");
+            popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true);
+        }
+
+        function evaluateCallback(result)
+        {
+            if (result.isError())
+                return;
+            if (!WebInspector.panels.scripts.paused)
+                return;
+            showObjectPopup.call(this, result);
+        }
+        WebInspector.panels.scripts.evaluateInSelectedCallFrame(element.textContent, false, this._popoverObjectGroup, false, evaluateCallback.bind(this));
+    },
+
+    _editBreakpointCondition: function(lineNumber, condition, callback)
+    {
+        this._conditionElement = this._createConditionElement(lineNumber);
+        this._textViewer.addDecoration(lineNumber, this._conditionElement);
+
+        function finishEditing(committed, element, newText)
+        {
+            this._textViewer.removeDecoration(lineNumber, this._conditionElement);
+            delete this._conditionEditorElement;
+            delete this._conditionElement;
+            callback(committed, newText);
+        }
+
+        WebInspector.startEditing(this._conditionEditorElement, {
+            context: null,
+            commitHandler: finishEditing.bind(this, true),
+            cancelHandler: finishEditing.bind(this, false)
+        });
+        this._conditionEditorElement.value = condition;
+        this._conditionEditorElement.select();
+    },
+
+    _createConditionElement: function(lineNumber)
+    {
+        var conditionElement = document.createElement("div");
+        conditionElement.className = "source-frame-breakpoint-condition";
+
+        var labelElement = document.createElement("label");
+        labelElement.className = "source-frame-breakpoint-message";
+        labelElement.htmlFor = "source-frame-breakpoint-condition";
+        labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber)));
+        conditionElement.appendChild(labelElement);
+
+        var editorElement = document.createElement("input");
+        editorElement.id = "source-frame-breakpoint-condition";
+        editorElement.className = "monospace";
+        editorElement.type = "text";
+        conditionElement.appendChild(editorElement);
+        this._conditionEditorElement = editorElement;
+
+        return conditionElement;
+    },
+
+    _evalSelectionInCallFrame: function(event)
+    {
+        if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+            return;
+
+        var selection = this.element.contentWindow.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var expression = selection.getRangeAt(0).toString().trim();
+        WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result) {
+            WebInspector.showConsole();
+            var commandMessage = new WebInspector.ConsoleCommand(expression);
+            WebInspector.console.addMessage(commandMessage);
+            WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, commandMessage));
+        });
+    },
+
+    resize: function()
+    {
+        if (this._textViewer)
+            this._textViewer.resize();
+    },
+
+    formatSource: function()
+    {
+        if (!this._content)
+            return;
+
+        function didFormat(formattedContent)
+        {
+            this._content = formattedContent;
+            this._textModel.setText(null, formattedContent.text);
+            this._setTextViewerDecorations();
+        }
+        var formatter = new WebInspector.ScriptFormatter();
+        formatter.formatContent(this._content, didFormat.bind(this))
+    },
+
+    _continueToLine: function(lineNumber)
+    {
+        var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+        if (location.sourceID)
+            WebInspector.debuggerModel.continueToLocation(location.sourceID, location.lineNumber, location.columnNumber);
+    },
+
+    _doubleClick: function(event)
+    {
+        if (!Preferences.canEditScriptSource || !this._isScript)
+            return;
+
+        var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content");
+        if (!lineRow)
+            return;  // Do not trigger editing from line numbers.
+
+        var lineNumber = lineRow.lineNumber;
+        var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+        if (!location.sourceID)
+            return;
+
+        function didEditLine(newContent)
+        {
+            var lines = [];
+            var oldLines = this._content.text.split('\n');
+            for (var i = 0; i < oldLines.length; ++i) {
+                if (i === lineNumber)
+                    lines.push(newContent);
+                else
+                    lines.push(oldLines[i]);
+            }
+            WebInspector.debuggerModel.editScriptSource(location.sourceID, lines.join("\n"));
+        }
+        this._textViewer.editLine(lineRow, didEditLine.bind(this));
+    },
+
+    _setBreakpoint: function(lineNumber, condition, enabled)
+    {
+        var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+        if (this._url)
+            WebInspector.debuggerModel.setBreakpoint(this._url, location.lineNumber, location.columnNumber, condition, enabled);
+        else if (location.sourceID)
+            WebInspector.debuggerModel.setBreakpointBySourceId(location.sourceID, location.lineNumber, location.columnNumber, condition, enabled);
+        else
+            return;
+
+        if (!WebInspector.panels.scripts.breakpointsActivated)
+            WebInspector.panels.scripts.toggleBreakpointsClicked();
+    },
+
+    _findBreakpoint: function(textViewerLineNumber)
+    {
+        var breakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
+        return WebInspector.debuggerModel.breakpointForId(breakpointId);
+    }
+}
+
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;
+
+
+WebInspector.SourceFrameContentProvider = function()
+{
+}
+
+WebInspector.SourceFrameContentProvider.prototype = {
+    requestContent: function(callback)
+    {
+        // Should be implemented by subclasses.
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrameContent.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrameContent.js
new file mode 100644
index 0000000..91b397b
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceFrameContent.js
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceFrameContent = function(text, mapping, scriptRanges)
+{
+    this._text = text;
+    this._mapping = mapping;
+    this._scriptRanges = scriptRanges;
+}
+
+WebInspector.SourceFrameContent.prototype = {
+    get text()
+    {
+        return this._text;
+    },
+
+    get scriptRanges()
+    {
+        return this._scriptRanges;
+    },
+
+    sourceFrameLineNumberToActualLocation: function(lineNumber)
+    {
+        // Script content may start right after <script> tag without new line (e.g. "<script>function f()...").
+        // In that case, column number should be equal to script column offset.
+        var columnNumber = 0;
+        for (var i = 0; i < this._scriptRanges.length; ++i) {
+            var scriptRange = this._scriptRanges[i];
+            if (scriptRange.start.lineNumber < lineNumber)
+                continue;
+            if (scriptRange.start.lineNumber === lineNumber)
+                columnNumber = scriptRange.start.columnNumber;
+            break;
+        }
+        var location = this._mapping.sourceLocationToActualLocation(lineNumber, columnNumber);
+        location.sourceID = this._sourceIDForSourceFrameLineNumber(lineNumber);
+        return location;
+    },
+
+    actualLocationToSourceFrameLineNumber: function(lineNumber, columnNumber)
+    {
+        return this._mapping.actualLocationToSourceLocation(lineNumber, columnNumber).lineNumber;
+    },
+
+    _sourceIDForSourceFrameLineNumber: function(lineNumber)
+    {
+        for (var i = 0; i < this._scriptRanges.length; ++i) {
+            var scriptRange = this._scriptRanges[i];
+            if (lineNumber < scriptRange.start.lineNumber)
+                return;
+            if (lineNumber > scriptRange.end.lineNumber)
+                continue;
+            if (lineNumber === scriptRange.end.lineNumber && !scriptRange.end.columnNumber)
+                continue;
+            return scriptRange.sourceID;
+        }
+    }
+}
+
+
+WebInspector.SourceMapping = function()
+{
+}
+
+WebInspector.SourceMapping.prototype = {
+    actualLocationToSourceLocation: function(lineNumber, columnNumber)
+    {
+        // Should be implemented by subclasses.
+    },
+
+    sourceLocationToActualLocation: function(lineNumber, columnNumber)
+    {
+        // Should be implemented by subclasses.
+    }
+}
+
+
+WebInspector.IdenticalSourceMapping = function()
+{
+    WebInspector.SourceMapping.call(this);
+}
+
+WebInspector.IdenticalSourceMapping.prototype = {
+    actualLocationToSourceLocation: function(lineNumber, columnNumber)
+    {
+        return { lineNumber: lineNumber, columnNumber: columnNumber};
+    },
+
+    sourceLocationToActualLocation: function(lineNumber, columnNumber)
+    {
+        return { lineNumber: lineNumber, columnNumber: columnNumber};
+    }
+}
+
+WebInspector.IdenticalSourceMapping.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.js
new file mode 100644
index 0000000..48c5bd4
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.js
@@ -0,0 +1,780 @@
+/* Generated by re2c 0.13.5 on Fri Jan 28 18:32:27 2011 */
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceHTMLTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: case 1: var yych|'
+
+WebInspector.SourceHTMLTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    // The order is determined by the generated code.
+    this._lexConditions = {
+        INITIAL: 0,
+        COMMENT: 1,
+        DOCTYPE: 2,
+        TAG: 3,
+        DSTRING: 4,
+        SSTRING: 5
+    };
+    this.case_INITIAL = 1000;
+    this.case_COMMENT = 1001;
+    this.case_DOCTYPE = 1002;
+    this.case_TAG = 1003;
+    this.case_DSTRING = 1004;
+    this.case_SSTRING = 1005;
+
+    this._parseConditions = {
+        INITIAL: 0,
+        ATTRIBUTE: 1,
+        ATTRIBUTE_VALUE: 2,
+        LINKIFY: 4,
+        A_NODE: 8,
+        SCRIPT: 16,
+        STYLE: 32
+    };
+
+    this.initialCondition = { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL };
+    this.condition = this.initialCondition;
+}
+
+WebInspector.SourceHTMLTokenizer.prototype = {
+    set line(line) {
+        if (this._internalJavaScriptTokenizer) {
+            var match = /<\/script/i.exec(line);
+            if (match) {
+                this._internalJavaScriptTokenizer.line = line.substring(0, match.index);
+            } else
+                this._internalJavaScriptTokenizer.line = line;
+        } else if (this._internalCSSTokenizer) {
+            var match = /<\/style/i.exec(line);
+            if (match) {
+                this._internalCSSTokenizer.line = line.substring(0, match.index);
+            } else
+                this._internalCSSTokenizer.line = line;
+        }
+        this._line = line;
+    },
+
+    _isExpectingAttribute: function()
+    {
+        return this._condition.parseCondition & this._parseConditions.ATTRIBUTE;
+    },
+
+    _isExpectingAttributeValue: function()
+    {
+        return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_VALUE;
+    },
+
+    _setExpectingAttribute: function()
+    {
+        if (this._isExpectingAttributeValue())
+            this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VALUE;
+        this._condition.parseCondition |= this._parseConditions.ATTRIBUTE;
+    },
+
+    _setExpectingAttributeValue: function()
+    {
+        if (this._isExpectingAttribute())
+            this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE;
+        this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE;
+    },
+
+    _stringToken: function(cursor, stringEnds)
+    {
+        if (!this._isExpectingAttributeValue()) {
+            this.tokenType = null;
+            return cursor;
+        }
+        this.tokenType = this._attrValueTokenType();
+        if (stringEnds)
+            this._setExpectingAttribute();
+        return cursor;
+    },
+
+    _attrValueTokenType: function()
+    {
+        if (this._condition.parseCondition & this._parseConditions.LINKIFY) {
+            if (this._condition.parseCondition & this._parseConditions.A_NODE)
+                return "html-external-link";
+            return "html-resource-link";
+        }
+        return "html-attribute-value";
+    },
+
+    nextToken: function(cursor)
+    {
+        if (this._internalJavaScriptTokenizer) {
+            // Re-set line to force </script> detection first.
+            this.line = this._line;
+            if (cursor !== this._internalJavaScriptTokenizer._line.length) {
+                // Tokenizer is stateless, so restore its condition before tokenizing and save it after.
+                this._internalJavaScriptTokenizer.condition = this._condition.internalJavaScriptTokenizerCondition;
+                var result = this._internalJavaScriptTokenizer.nextToken(cursor);
+                this.tokenType = this._internalJavaScriptTokenizer.tokenType;
+                this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.condition;
+                return result;
+            } else if (cursor !== this._line.length)
+                delete this._internalJavaScriptTokenizer;
+        } else if (this._internalCSSTokenizer) {
+            // Re-set line to force </style> detection first.
+            this.line = this._line;
+            if (cursor !== this._internalCSSTokenizer._line.length) {
+                // Tokenizer is stateless, so restore its condition before tokenizing and save it after.
+                this._internalCSSTokenizer.condition = this._condition.internalCSSTokenizerCondition;
+                var result = this._internalCSSTokenizer.nextToken(cursor);
+                this.tokenType = this._internalCSSTokenizer.tokenType;
+                this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.condition;
+                return result;
+            } else if (cursor !== this._line.length)
+                delete this._internalCSSTokenizer;
+        }
+
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            
+        {
+            case 1: var yych;
+            var yyaccept = 0;
+            if (this.getLexCondition() < 3) {
+                if (this.getLexCondition() < 1) {
+                    { gotoCase = this.case_INITIAL; continue; };
+                } else {
+                    if (this.getLexCondition() < 2) {
+                        { gotoCase = this.case_COMMENT; continue; };
+                    } else {
+                        { gotoCase = this.case_DOCTYPE; continue; };
+                    }
+                }
+            } else {
+                if (this.getLexCondition() < 4) {
+                    { gotoCase = this.case_TAG; continue; };
+                } else {
+                    if (this.getLexCondition() < 5) {
+                        { gotoCase = this.case_DSTRING; continue; };
+                    } else {
+                        { gotoCase = this.case_SSTRING; continue; };
+                    }
+                }
+            }
+/* *********************************** */
+case this.case_COMMENT:
+
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 4; continue; };
+                { gotoCase = 3; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 4; continue; };
+                if (yych == '-') { gotoCase = 6; continue; };
+                { gotoCase = 3; continue; };
+            }
+case 2:
+            { this.tokenType = "html-comment"; return cursor; }
+case 3:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 9; continue; };
+case 4:
+            ++cursor;
+case 5:
+            { this.tokenType = null; return cursor; }
+case 6:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych != '-') { gotoCase = 5; continue; };
+case 7:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '>') { gotoCase = 10; continue; };
+case 8:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 9:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 2; continue; };
+                { gotoCase = 8; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 2; continue; };
+                if (yych == '-') { gotoCase = 12; continue; };
+                { gotoCase = 8; continue; };
+            }
+case 10:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.INITIAL);
+            { this.tokenType = "html-comment"; return cursor; }
+case 12:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '-') { gotoCase = 7; continue; };
+            cursor = YYMARKER;
+            if (yyaccept <= 0) {
+                { gotoCase = 2; continue; };
+            } else {
+                { gotoCase = 5; continue; };
+            }
+/* *********************************** */
+case this.case_DOCTYPE:
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 18; continue; };
+                { gotoCase = 17; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 18; continue; };
+                if (yych == '>') { gotoCase = 20; continue; };
+                { gotoCase = 17; continue; };
+            }
+case 16:
+            { this.tokenType = "html-doctype"; return cursor; }
+case 17:
+            yych = this._charAt(++cursor);
+            { gotoCase = 23; continue; };
+case 18:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 20:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.INITIAL);
+            { this.tokenType = "html-doctype"; return cursor; }
+case 22:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 23:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 16; continue; };
+                { gotoCase = 22; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 16; continue; };
+                if (yych == '>') { gotoCase = 16; continue; };
+                { gotoCase = 22; continue; };
+            }
+/* *********************************** */
+case this.case_DSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 28; continue; };
+                { gotoCase = 27; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 28; continue; };
+                if (yych == '"') { gotoCase = 30; continue; };
+                { gotoCase = 27; continue; };
+            }
+case 26:
+            { return this._stringToken(cursor); }
+case 27:
+            yych = this._charAt(++cursor);
+            { gotoCase = 34; continue; };
+case 28:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 30:
+            ++cursor;
+case 31:
+            this.setLexCondition(this._lexConditions.TAG);
+            { return this._stringToken(cursor, true); }
+case 32:
+            yych = this._charAt(++cursor);
+            { gotoCase = 31; continue; };
+case 33:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 34:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 26; continue; };
+                { gotoCase = 33; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 26; continue; };
+                if (yych == '"') { gotoCase = 32; continue; };
+                { gotoCase = 33; continue; };
+            }
+/* *********************************** */
+case this.case_INITIAL:
+            yych = this._charAt(cursor);
+            if (yych == '<') { gotoCase = 39; continue; };
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 39:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '/') {
+                if (yych == '!') { gotoCase = 44; continue; };
+                if (yych >= '/') { gotoCase = 41; continue; };
+            } else {
+                if (yych <= 'S') {
+                    if (yych >= 'S') { gotoCase = 42; continue; };
+                } else {
+                    if (yych == 's') { gotoCase = 42; continue; };
+                }
+            }
+case 40:
+            this.setLexCondition(this._lexConditions.TAG);
+            {
+                    if (this._condition.parseCondition & (this._parseConditions.SCRIPT | this._parseConditions.STYLE)) {
+                        // Do not tokenize script and style tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    this.tokenType = "html-tag";
+                    return cursor;
+                }
+case 41:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == 'S') { gotoCase = 73; continue; };
+            if (yych == 's') { gotoCase = 73; continue; };
+            { gotoCase = 40; continue; };
+case 42:
+            yych = this._charAt(++cursor);
+            if (yych <= 'T') {
+                if (yych == 'C') { gotoCase = 62; continue; };
+                if (yych >= 'T') { gotoCase = 63; continue; };
+            } else {
+                if (yych <= 'c') {
+                    if (yych >= 'c') { gotoCase = 62; continue; };
+                } else {
+                    if (yych == 't') { gotoCase = 63; continue; };
+                }
+            }
+case 43:
+            cursor = YYMARKER;
+            { gotoCase = 40; continue; };
+case 44:
+            yych = this._charAt(++cursor);
+            if (yych <= 'C') {
+                if (yych != '-') { gotoCase = 43; continue; };
+            } else {
+                if (yych <= 'D') { gotoCase = 46; continue; };
+                if (yych == 'd') { gotoCase = 46; continue; };
+                { gotoCase = 43; continue; };
+            }
+            yych = this._charAt(++cursor);
+            if (yych == '-') { gotoCase = 54; continue; };
+            { gotoCase = 43; continue; };
+case 46:
+            yych = this._charAt(++cursor);
+            if (yych == 'O') { gotoCase = 47; continue; };
+            if (yych != 'o') { gotoCase = 43; continue; };
+case 47:
+            yych = this._charAt(++cursor);
+            if (yych == 'C') { gotoCase = 48; continue; };
+            if (yych != 'c') { gotoCase = 43; continue; };
+case 48:
+            yych = this._charAt(++cursor);
+            if (yych == 'T') { gotoCase = 49; continue; };
+            if (yych != 't') { gotoCase = 43; continue; };
+case 49:
+            yych = this._charAt(++cursor);
+            if (yych == 'Y') { gotoCase = 50; continue; };
+            if (yych != 'y') { gotoCase = 43; continue; };
+case 50:
+            yych = this._charAt(++cursor);
+            if (yych == 'P') { gotoCase = 51; continue; };
+            if (yych != 'p') { gotoCase = 43; continue; };
+case 51:
+            yych = this._charAt(++cursor);
+            if (yych == 'E') { gotoCase = 52; continue; };
+            if (yych != 'e') { gotoCase = 43; continue; };
+case 52:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DOCTYPE);
+            { this.tokenType = "html-doctype"; return cursor; }
+case 54:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 57; continue; };
+                { gotoCase = 54; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 57; continue; };
+                if (yych != '-') { gotoCase = 54; continue; };
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '-') { gotoCase = 59; continue; };
+            { gotoCase = 43; continue; };
+case 57:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.COMMENT);
+            { this.tokenType = "html-comment"; return cursor; }
+case 59:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych != '>') { gotoCase = 54; continue; };
+            ++cursor;
+            { this.tokenType = "html-comment"; return cursor; }
+case 62:
+            yych = this._charAt(++cursor);
+            if (yych == 'R') { gotoCase = 68; continue; };
+            if (yych == 'r') { gotoCase = 68; continue; };
+            { gotoCase = 43; continue; };
+case 63:
+            yych = this._charAt(++cursor);
+            if (yych == 'Y') { gotoCase = 64; continue; };
+            if (yych != 'y') { gotoCase = 43; continue; };
+case 64:
+            yych = this._charAt(++cursor);
+            if (yych == 'L') { gotoCase = 65; continue; };
+            if (yych != 'l') { gotoCase = 43; continue; };
+case 65:
+            yych = this._charAt(++cursor);
+            if (yych == 'E') { gotoCase = 66; continue; };
+            if (yych != 'e') { gotoCase = 43; continue; };
+case 66:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.TAG);
+            {
+                    if (this._condition.parseCondition & this._parseConditions.STYLE) {
+                        // Do not tokenize style tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.STYLE;
+                    this._setExpectingAttribute();
+                    return cursor;
+                }
+case 68:
+            yych = this._charAt(++cursor);
+            if (yych == 'I') { gotoCase = 69; continue; };
+            if (yych != 'i') { gotoCase = 43; continue; };
+case 69:
+            yych = this._charAt(++cursor);
+            if (yych == 'P') { gotoCase = 70; continue; };
+            if (yych != 'p') { gotoCase = 43; continue; };
+case 70:
+            yych = this._charAt(++cursor);
+            if (yych == 'T') { gotoCase = 71; continue; };
+            if (yych != 't') { gotoCase = 43; continue; };
+case 71:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.TAG);
+            {
+                    if (this._condition.parseCondition & this._parseConditions.SCRIPT) {
+                        // Do not tokenize script tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.SCRIPT;
+                    this._setExpectingAttribute();
+                    return cursor;
+                }
+case 73:
+            yych = this._charAt(++cursor);
+            if (yych <= 'T') {
+                if (yych == 'C') { gotoCase = 75; continue; };
+                if (yych <= 'S') { gotoCase = 43; continue; };
+            } else {
+                if (yych <= 'c') {
+                    if (yych <= 'b') { gotoCase = 43; continue; };
+                    { gotoCase = 75; continue; };
+                } else {
+                    if (yych != 't') { gotoCase = 43; continue; };
+                }
+            }
+            yych = this._charAt(++cursor);
+            if (yych == 'Y') { gotoCase = 81; continue; };
+            if (yych == 'y') { gotoCase = 81; continue; };
+            { gotoCase = 43; continue; };
+case 75:
+            yych = this._charAt(++cursor);
+            if (yych == 'R') { gotoCase = 76; continue; };
+            if (yych != 'r') { gotoCase = 43; continue; };
+case 76:
+            yych = this._charAt(++cursor);
+            if (yych == 'I') { gotoCase = 77; continue; };
+            if (yych != 'i') { gotoCase = 43; continue; };
+case 77:
+            yych = this._charAt(++cursor);
+            if (yych == 'P') { gotoCase = 78; continue; };
+            if (yych != 'p') { gotoCase = 43; continue; };
+case 78:
+            yych = this._charAt(++cursor);
+            if (yych == 'T') { gotoCase = 79; continue; };
+            if (yych != 't') { gotoCase = 43; continue; };
+case 79:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.TAG);
+            {
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+case 81:
+            yych = this._charAt(++cursor);
+            if (yych == 'L') { gotoCase = 82; continue; };
+            if (yych != 'l') { gotoCase = 43; continue; };
+case 82:
+            yych = this._charAt(++cursor);
+            if (yych == 'E') { gotoCase = 83; continue; };
+            if (yych != 'e') { gotoCase = 43; continue; };
+case 83:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.TAG);
+            {
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+/* *********************************** */
+case this.case_SSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 89; continue; };
+                { gotoCase = 88; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 89; continue; };
+                if (yych == '\'') { gotoCase = 91; continue; };
+                { gotoCase = 88; continue; };
+            }
+case 87:
+            { return this._stringToken(cursor); }
+case 88:
+            yych = this._charAt(++cursor);
+            { gotoCase = 95; continue; };
+case 89:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 91:
+            ++cursor;
+case 92:
+            this.setLexCondition(this._lexConditions.TAG);
+            { return this._stringToken(cursor, true); }
+case 93:
+            yych = this._charAt(++cursor);
+            { gotoCase = 92; continue; };
+case 94:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 95:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 87; continue; };
+                { gotoCase = 94; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 87; continue; };
+                if (yych == '\'') { gotoCase = 93; continue; };
+                { gotoCase = 94; continue; };
+            }
+/* *********************************** */
+case this.case_TAG:
+            yych = this._charAt(cursor);
+            if (yych <= '&') {
+                if (yych <= '\r') {
+                    if (yych == '\n') { gotoCase = 100; continue; };
+                    if (yych >= '\r') { gotoCase = 100; continue; };
+                } else {
+                    if (yych <= ' ') {
+                        if (yych >= ' ') { gotoCase = 100; continue; };
+                    } else {
+                        if (yych == '"') { gotoCase = 102; continue; };
+                    }
+                }
+            } else {
+                if (yych <= '>') {
+                    if (yych <= ';') {
+                        if (yych <= '\'') { gotoCase = 103; continue; };
+                    } else {
+                        if (yych <= '<') { gotoCase = 100; continue; };
+                        if (yych <= '=') { gotoCase = 104; continue; };
+                        { gotoCase = 106; continue; };
+                    }
+                } else {
+                    if (yych <= '[') {
+                        if (yych >= '[') { gotoCase = 100; continue; };
+                    } else {
+                        if (yych == ']') { gotoCase = 100; continue; };
+                    }
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 119; continue; };
+case 99:
+            {
+                    if (this._condition.parseCondition === this._parseConditions.SCRIPT || this._condition.parseCondition === this._parseConditions.STYLE) {
+                        // Fall through if expecting attributes.
+                        this.tokenType = null;
+                        return cursor;
+                    }
+
+                    if (this._condition.parseCondition === this._parseConditions.INITIAL) {
+                        this.tokenType = "html-tag";
+                        this._setExpectingAttribute();
+                        var token = this._line.substring(cursorOnEnter, cursor);
+                        if (token === "a")
+                            this._condition.parseCondition |= this._parseConditions.A_NODE;
+                        else if (this._condition.parseCondition & this._parseConditions.A_NODE)
+                            this._condition.parseCondition ^= this._parseConditions.A_NODE;
+                    } else if (this._isExpectingAttribute()) {
+                        var token = this._line.substring(cursorOnEnter, cursor);
+                        if (token === "href" || token === "src")
+                            this._condition.parseCondition |= this._parseConditions.LINKIFY;
+                        else if (this._condition.parseCondition |= this._parseConditions.LINKIFY)
+                            this._condition.parseCondition ^= this._parseConditions.LINKIFY;
+                        this.tokenType = "html-attribute-name";
+                    } else if (this._isExpectingAttributeValue())
+                        this.tokenType = this._attrValueTokenType();
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+case 100:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 102:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 115; continue; };
+case 103:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 109; continue; };
+case 104:
+            ++cursor;
+            {
+                    if (this._isExpectingAttribute())
+                        this._setExpectingAttributeValue();
+                    this.tokenType = null;
+                    return cursor;
+                }
+case 106:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.INITIAL);
+            {
+                    this.tokenType = "html-tag";
+                    if (this._condition.parseCondition & this._parseConditions.SCRIPT) {
+                        if (!this._internalJavaScriptTokenizer) {
+                            this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript");
+                            this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition;
+                        }
+                        // Do not tokenize script tag contents.
+                        return cursor;
+                    }
+
+                    if (this._condition.parseCondition & this._parseConditions.STYLE) {
+                        if (!this._internalCSSTokenizer) {
+                            this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css");
+                            this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition;
+                        }
+                        // Do not tokenize style tag contents.
+                        return cursor;
+                    }
+
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+case 108:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 109:
+            if (yych <= '\f') {
+                if (yych != '\n') { gotoCase = 108; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 110; continue; };
+                if (yych == '\'') { gotoCase = 112; continue; };
+                { gotoCase = 108; continue; };
+            }
+case 110:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.SSTRING);
+            { return this._stringToken(cursor); }
+case 112:
+            ++cursor;
+            { return this._stringToken(cursor, true); }
+case 114:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 115:
+            if (yych <= '\f') {
+                if (yych != '\n') { gotoCase = 114; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 116; continue; };
+                if (yych == '"') { gotoCase = 112; continue; };
+                { gotoCase = 114; continue; };
+            }
+case 116:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DSTRING);
+            { return this._stringToken(cursor); }
+case 118:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 119:
+            if (yych <= '"') {
+                if (yych <= '\r') {
+                    if (yych == '\n') { gotoCase = 99; continue; };
+                    if (yych <= '\f') { gotoCase = 118; continue; };
+                    { gotoCase = 99; continue; };
+                } else {
+                    if (yych == ' ') { gotoCase = 99; continue; };
+                    if (yych <= '!') { gotoCase = 118; continue; };
+                    { gotoCase = 99; continue; };
+                }
+            } else {
+                if (yych <= '>') {
+                    if (yych == '\'') { gotoCase = 99; continue; };
+                    if (yych <= ';') { gotoCase = 118; continue; };
+                    { gotoCase = 99; continue; };
+                } else {
+                    if (yych <= '[') {
+                        if (yych <= 'Z') { gotoCase = 118; continue; };
+                        { gotoCase = 99; continue; };
+                    } else {
+                        if (yych == ']') { gotoCase = 99; continue; };
+                        { gotoCase = 118; continue; };
+                    }
+                }
+            }
+        }
+
+        }
+    }
+}
+
+WebInspector.SourceHTMLTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js
new file mode 100644
index 0000000..769e984
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceHTMLTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|goto case \([^;]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: var yych|'
+
+WebInspector.SourceHTMLTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    // The order is determined by the generated code.
+    this._lexConditions = {
+        INITIAL: 0,
+        COMMENT: 1,
+        DOCTYPE: 2,
+        TAG: 3,
+        DSTRING: 4,
+        SSTRING: 5
+    };
+    this.case_INITIAL = 1000;
+    this.case_COMMENT = 1001;
+    this.case_DOCTYPE = 1002;
+    this.case_TAG = 1003;
+    this.case_DSTRING = 1004;
+    this.case_SSTRING = 1005;
+
+    this._parseConditions = {
+        INITIAL: 0,
+        ATTRIBUTE: 1,
+        ATTRIBUTE_VALUE: 2,
+        LINKIFY: 4,
+        A_NODE: 8,
+        SCRIPT: 16,
+        STYLE: 32
+    };
+
+    this.initialCondition = { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL };
+    this.condition = this.initialCondition;
+}
+
+WebInspector.SourceHTMLTokenizer.prototype = {
+    set line(line) {
+        if (this._internalJavaScriptTokenizer) {
+            var match = /<\/script/i.exec(line);
+            if (match) {
+                this._internalJavaScriptTokenizer.line = line.substring(0, match.index);
+            } else
+                this._internalJavaScriptTokenizer.line = line;
+        } else if (this._internalCSSTokenizer) {
+            var match = /<\/style/i.exec(line);
+            if (match) {
+                this._internalCSSTokenizer.line = line.substring(0, match.index);
+            } else
+                this._internalCSSTokenizer.line = line;
+        }
+        this._line = line;
+    },
+
+    _isExpectingAttribute: function()
+    {
+        return this._condition.parseCondition & this._parseConditions.ATTRIBUTE;
+    },
+
+    _isExpectingAttributeValue: function()
+    {
+        return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_VALUE;
+    },
+
+    _setExpectingAttribute: function()
+    {
+        if (this._isExpectingAttributeValue())
+            this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VALUE;
+        this._condition.parseCondition |= this._parseConditions.ATTRIBUTE;
+    },
+
+    _setExpectingAttributeValue: function()
+    {
+        if (this._isExpectingAttribute())
+            this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE;
+        this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE;
+    },
+
+    _stringToken: function(cursor, stringEnds)
+    {
+        if (!this._isExpectingAttributeValue()) {
+            this.tokenType = null;
+            return cursor;
+        }
+        this.tokenType = this._attrValueTokenType();
+        if (stringEnds)
+            this._setExpectingAttribute();
+        return cursor;
+    },
+
+    _attrValueTokenType: function()
+    {
+        if (this._condition.parseCondition & this._parseConditions.LINKIFY) {
+            if (this._condition.parseCondition & this._parseConditions.A_NODE)
+                return "html-external-link";
+            return "html-resource-link";
+        }
+        return "html-attribute-value";
+    },
+
+    nextToken: function(cursor)
+    {
+        if (this._internalJavaScriptTokenizer) {
+            // Re-set line to force </script> detection first.
+            this.line = this._line;
+            if (cursor !== this._internalJavaScriptTokenizer._line.length) {
+                // Tokenizer is stateless, so restore its condition before tokenizing and save it after.
+                this._internalJavaScriptTokenizer.condition = this._condition.internalJavaScriptTokenizerCondition;
+                var result = this._internalJavaScriptTokenizer.nextToken(cursor);
+                this.tokenType = this._internalJavaScriptTokenizer.tokenType;
+                this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.condition;
+                return result;
+            } else if (cursor !== this._line.length)
+                delete this._internalJavaScriptTokenizer;
+        } else if (this._internalCSSTokenizer) {
+            // Re-set line to force </style> detection first.
+            this.line = this._line;
+            if (cursor !== this._internalCSSTokenizer._line.length) {
+                // Tokenizer is stateless, so restore its condition before tokenizing and save it after.
+                this._internalCSSTokenizer.condition = this._condition.internalCSSTokenizerCondition;
+                var result = this._internalCSSTokenizer.nextToken(cursor);
+                this.tokenType = this._internalCSSTokenizer.tokenType;
+                this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.condition;
+                return result;
+            } else if (cursor !== this._line.length)
+                delete this._internalCSSTokenizer;
+        }
+
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            /*!re2c
+                re2c:define:YYCTYPE  = "var";
+                re2c:define:YYCURSOR = cursor;
+                re2c:define:YYGETCONDITION = "this.getLexCondition";
+                re2c:define:YYSETCONDITION = "this.setLexCondition";
+                re2c:condprefix = "case this.case_";
+                re2c:condenumprefix = "this._lexConditions.";
+                re2c:yyfill:enable = 0;
+                re2c:labelprefix = "case ";
+                re2c:indent:top = 2;
+                re2c:indent:string = "    ";
+
+                CommentContent = ([^-\r\n] | ("--" [^>]))*;
+                Comment = "<!--" CommentContent "-->";
+                CommentStart = "<!--" CommentContent [\r\n];
+                CommentEnd = CommentContent "-->";
+
+                DocTypeStart = "<!" [Dd] [Oo] [Cc] [Tt] [Yy] [Pp] [Ee];
+                DocTypeContent = [^\r\n>]*;
+
+                ScriptStart = "<" [Ss] [Cc] [Rr] [Ii] [Pp] [Tt];
+                ScriptEnd = "</" [Ss] [Cc] [Rr] [Ii] [Pp] [Tt];
+
+                StyleStart = "<" [Ss] [Tt] [Yy] [Ll] [Ee];
+                StyleEnd = "</" [Ss] [Tt] [Yy] [Ll] [Ee];
+
+                LT = "<" | "</";
+                GT = ">";
+                EqualSign = "=";
+
+                DoubleStringContent = [^\r\n\"]*;
+                SingleStringContent = [^\r\n\']*;
+                StringLiteral = "\"" DoubleStringContent "\"" | "'" SingleStringContent "'";
+                DoubleStringStart = "\"" DoubleStringContent [\r\n];
+                DoubleStringEnd = DoubleStringContent "\"";
+                SingleStringStart = "'" SingleStringContent [\r\n];
+                SingleStringEnd = SingleStringContent "'";
+
+                Identifier = [^ \r\n"'<>\[\]=]+;
+
+                <INITIAL> Comment { this.tokenType = "html-comment"; return cursor; }
+                <INITIAL> CommentStart => COMMENT { this.tokenType = "html-comment"; return cursor; }
+                <COMMENT> CommentContent => COMMENT { this.tokenType = "html-comment"; return cursor; }
+                <COMMENT> CommentEnd => INITIAL { this.tokenType = "html-comment"; return cursor; }
+
+                <INITIAL> DocTypeStart => DOCTYPE { this.tokenType = "html-doctype"; return cursor; }
+                <DOCTYPE> DocTypeContent => DOCTYPE { this.tokenType = "html-doctype"; return cursor; }
+                <DOCTYPE> GT => INITIAL { this.tokenType = "html-doctype"; return cursor; }
+
+                <INITIAL> ScriptStart => TAG
+                {
+                    if (this._condition.parseCondition & this._parseConditions.SCRIPT) {
+                        // Do not tokenize script tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.SCRIPT;
+                    this._setExpectingAttribute();
+                    return cursor;
+                }
+
+                <INITIAL> ScriptEnd => TAG
+                {
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+
+                <INITIAL> StyleStart => TAG
+                {
+                    if (this._condition.parseCondition & this._parseConditions.STYLE) {
+                        // Do not tokenize style tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.STYLE;
+                    this._setExpectingAttribute();
+                    return cursor;
+                }
+
+                <INITIAL> StyleEnd => TAG
+                {
+                    this.tokenType = "html-tag";
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+
+                <INITIAL> LT => TAG
+                {
+                    if (this._condition.parseCondition & (this._parseConditions.SCRIPT | this._parseConditions.STYLE)) {
+                        // Do not tokenize script and style tag contents, keep lexer state, even though processing "<".
+                        this.setLexCondition(this._lexConditions.INITIAL);
+                        this.tokenType = null;
+                        return cursor;
+                    }
+
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    this.tokenType = "html-tag";
+                    return cursor;
+                }
+  
+                <TAG> GT => INITIAL
+                {
+                    this.tokenType = "html-tag";
+                    if (this._condition.parseCondition & this._parseConditions.SCRIPT) {
+                        if (!this._internalJavaScriptTokenizer) {
+                            this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript");
+                            this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition;
+                        }
+                        // Do not tokenize script tag contents.
+                        return cursor;
+                    }
+
+                    if (this._condition.parseCondition & this._parseConditions.STYLE) {
+                        if (!this._internalCSSTokenizer) {
+                            this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css");
+                            this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition;
+                        }
+                        // Do not tokenize style tag contents.
+                        return cursor;
+                    }
+
+                    this._condition.parseCondition = this._parseConditions.INITIAL;
+                    return cursor;
+                }
+
+                <TAG> StringLiteral { return this._stringToken(cursor, true); }
+                <TAG> DoubleStringStart => DSTRING { return this._stringToken(cursor); }
+                <DSTRING> DoubleStringContent => DSTRING { return this._stringToken(cursor); }
+                <DSTRING> DoubleStringEnd => TAG { return this._stringToken(cursor, true); }
+                <TAG> SingleStringStart => SSTRING { return this._stringToken(cursor); }
+                <SSTRING> SingleStringContent => SSTRING { return this._stringToken(cursor); }
+                <SSTRING> SingleStringEnd => TAG { return this._stringToken(cursor, true); }
+
+                <TAG> EqualSign => TAG
+                {
+                    if (this._isExpectingAttribute())
+                        this._setExpectingAttributeValue();
+                    this.tokenType = null;
+                    return cursor;
+                }
+
+                <TAG> Identifier
+                {
+                    if (this._condition.parseCondition === this._parseConditions.SCRIPT || this._condition.parseCondition === this._parseConditions.STYLE) {
+                        // Fall through if expecting attributes.
+                        this.tokenType = null;
+                        return cursor;
+                    }
+
+                    if (this._condition.parseCondition === this._parseConditions.INITIAL) {
+                        this.tokenType = "html-tag";
+                        this._setExpectingAttribute();
+                        var token = this._line.substring(cursorOnEnter, cursor);
+                        if (token === "a")
+                            this._condition.parseCondition |= this._parseConditions.A_NODE;
+                        else if (this._condition.parseCondition & this._parseConditions.A_NODE)
+                            this._condition.parseCondition ^= this._parseConditions.A_NODE;
+                    } else if (this._isExpectingAttribute()) {
+                        var token = this._line.substring(cursorOnEnter, cursor);
+                        if (token === "href" || token === "src")
+                            this._condition.parseCondition |= this._parseConditions.LINKIFY;
+                        else if (this._condition.parseCondition |= this._parseConditions.LINKIFY)
+                            this._condition.parseCondition ^= this._parseConditions.LINKIFY;
+                        this.tokenType = "html-attribute-name";
+                    } else if (this._isExpectingAttributeValue())
+                        this.tokenType = this._attrValueTokenType();
+                    else
+                        this.tokenType = null;
+                    return cursor;
+                }
+                <*> [^] { this.tokenType = null; return cursor; }
+            */
+        }
+    }
+}
+
+WebInspector.SourceHTMLTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js
new file mode 100644
index 0000000..fbd44d7
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js
@@ -0,0 +1,2417 @@
+/* Generated by re2c 0.13.5 on Thu Feb 25 21:44:55 2010 */
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: case 1: var yych|'
+
+WebInspector.SourceJavaScriptTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    this._keywords = [
+        "null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for",
+        "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if",
+        "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger",
+        "class", "enum", "export", "extends", "import", "super", "get", "set", "with"
+    ].keySet();
+
+    this._lexConditions = {
+        DIV: 0,
+        NODIV: 1,
+        COMMENT: 2,
+        DSTRING: 3,
+        SSTRING: 4,
+        REGEX: 5
+    };
+
+    this.case_DIV = 1000;
+    this.case_NODIV = 1001;
+    this.case_COMMENT = 1002;
+    this.case_DSTRING = 1003;
+    this.case_SSTRING = 1004;
+    this.case_REGEX = 1005;
+
+    this.initialCondition = { lexCondition: this._lexConditions.NODIV }
+    this.condition = this.initialCondition;
+}
+
+WebInspector.SourceJavaScriptTokenizer.prototype = {
+    nextToken: function(cursor)
+    {
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            
+        {
+            case 1: var yych;
+            var yyaccept = 0;
+            if (this.getLexCondition() < 3) {
+                if (this.getLexCondition() < 1) {
+                    { gotoCase = this.case_DIV; continue; };
+                } else {
+                    if (this.getLexCondition() < 2) {
+                        { gotoCase = this.case_NODIV; continue; };
+                    } else {
+                        { gotoCase = this.case_COMMENT; continue; };
+                    }
+                }
+            } else {
+                if (this.getLexCondition() < 4) {
+                    { gotoCase = this.case_DSTRING; continue; };
+                } else {
+                    if (this.getLexCondition() < 5) {
+                        { gotoCase = this.case_SSTRING; continue; };
+                    } else {
+                        { gotoCase = this.case_REGEX; continue; };
+                    }
+                }
+            }
+/* *********************************** */
+case this.case_COMMENT:
+
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 4; continue; };
+                { gotoCase = 3; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 4; continue; };
+                if (yych == '*') { gotoCase = 6; continue; };
+                { gotoCase = 3; continue; };
+            }
+case 2:
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 3:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 12; continue; };
+case 4:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 6:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '*') { gotoCase = 9; continue; };
+            if (yych != '/') { gotoCase = 11; continue; };
+case 7:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 9:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '*') { gotoCase = 9; continue; };
+            if (yych == '/') { gotoCase = 7; continue; };
+case 11:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 12:
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 2; continue; };
+                { gotoCase = 11; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 2; continue; };
+                if (yych == '*') { gotoCase = 9; continue; };
+                { gotoCase = 11; continue; };
+            }
+/* *********************************** */
+case this.case_DIV:
+            yych = this._charAt(cursor);
+            if (yych <= '9') {
+                if (yych <= '(') {
+                    if (yych <= '#') {
+                        if (yych <= ' ') { gotoCase = 15; continue; };
+                        if (yych <= '!') { gotoCase = 17; continue; };
+                        if (yych <= '"') { gotoCase = 19; continue; };
+                    } else {
+                        if (yych <= '%') {
+                            if (yych <= '$') { gotoCase = 20; continue; };
+                            { gotoCase = 22; continue; };
+                        } else {
+                            if (yych <= '&') { gotoCase = 23; continue; };
+                            if (yych <= '\'') { gotoCase = 24; continue; };
+                            { gotoCase = 25; continue; };
+                        }
+                    }
+                } else {
+                    if (yych <= ',') {
+                        if (yych <= ')') { gotoCase = 26; continue; };
+                        if (yych <= '*') { gotoCase = 28; continue; };
+                        if (yych <= '+') { gotoCase = 29; continue; };
+                        { gotoCase = 25; continue; };
+                    } else {
+                        if (yych <= '.') {
+                            if (yych <= '-') { gotoCase = 30; continue; };
+                            { gotoCase = 31; continue; };
+                        } else {
+                            if (yych <= '/') { gotoCase = 32; continue; };
+                            if (yych <= '0') { gotoCase = 34; continue; };
+                            { gotoCase = 36; continue; };
+                        }
+                    }
+                }
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '>') {
+                        if (yych <= ';') { gotoCase = 25; continue; };
+                        if (yych <= '<') { gotoCase = 37; continue; };
+                        if (yych <= '=') { gotoCase = 38; continue; };
+                        { gotoCase = 39; continue; };
+                    } else {
+                        if (yych <= '@') {
+                            if (yych <= '?') { gotoCase = 25; continue; };
+                        } else {
+                            if (yych <= 'Z') { gotoCase = 20; continue; };
+                            if (yych <= '[') { gotoCase = 25; continue; };
+                            { gotoCase = 40; continue; };
+                        }
+                    }
+                } else {
+                    if (yych <= 'z') {
+                        if (yych <= '^') {
+                            if (yych <= ']') { gotoCase = 25; continue; };
+                            { gotoCase = 41; continue; };
+                        } else {
+                            if (yych != '`') { gotoCase = 20; continue; };
+                        }
+                    } else {
+                        if (yych <= '|') {
+                            if (yych <= '{') { gotoCase = 25; continue; };
+                            { gotoCase = 42; continue; };
+                        } else {
+                            if (yych <= '~') { gotoCase = 25; continue; };
+                            if (yych >= 0x80) { gotoCase = 20; continue; };
+                        }
+                    }
+                }
+            }
+case 15:
+            ++cursor;
+case 16:
+            { this.tokenType = null; return cursor; }
+case 17:
+            ++cursor;
+            if ((yych = this._charAt(cursor)) == '=') { gotoCase = 115; continue; };
+case 18:
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = null; return cursor; }
+case 19:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '\n') { gotoCase = 16; continue; };
+            if (yych == '\r') { gotoCase = 16; continue; };
+            { gotoCase = 107; continue; };
+case 20:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 50; continue; };
+case 21:
+            {
+                    var token = this._line.substring(cursorOnEnter, cursor);
+                    if (token in this._keywords)
+                        this.tokenType = "javascript-keyword";
+                    else
+                        this.tokenType = "javascript-ident";
+                    return cursor;
+                }
+case 22:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 23:
+            yych = this._charAt(++cursor);
+            if (yych == '&') { gotoCase = 43; continue; };
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 24:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '\n') { gotoCase = 16; continue; };
+            if (yych == '\r') { gotoCase = 16; continue; };
+            { gotoCase = 96; continue; };
+case 25:
+            yych = this._charAt(++cursor);
+            { gotoCase = 18; continue; };
+case 26:
+            ++cursor;
+            { this.tokenType = null; return cursor; }
+case 28:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 29:
+            yych = this._charAt(++cursor);
+            if (yych == '+') { gotoCase = 43; continue; };
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 30:
+            yych = this._charAt(++cursor);
+            if (yych == '-') { gotoCase = 43; continue; };
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 31:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 18; continue; };
+            if (yych <= '9') { gotoCase = 89; continue; };
+            { gotoCase = 18; continue; };
+case 32:
+            yyaccept = 2;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '.') {
+                if (yych == '*') { gotoCase = 78; continue; };
+            } else {
+                if (yych <= '/') { gotoCase = 80; continue; };
+                if (yych == '=') { gotoCase = 77; continue; };
+            }
+case 33:
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = null; return cursor; }
+case 34:
+            yyaccept = 3;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= 'E') {
+                if (yych <= '/') {
+                    if (yych == '.') { gotoCase = 63; continue; };
+                } else {
+                    if (yych <= '7') { gotoCase = 72; continue; };
+                    if (yych >= 'E') { gotoCase = 62; continue; };
+                }
+            } else {
+                if (yych <= 'd') {
+                    if (yych == 'X') { gotoCase = 74; continue; };
+                } else {
+                    if (yych <= 'e') { gotoCase = 62; continue; };
+                    if (yych == 'x') { gotoCase = 74; continue; };
+                }
+            }
+case 35:
+            { this.tokenType = "javascript-number"; return cursor; }
+case 36:
+            yyaccept = 3;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '9') {
+                if (yych == '.') { gotoCase = 63; continue; };
+                if (yych <= '/') { gotoCase = 35; continue; };
+                { gotoCase = 60; continue; };
+            } else {
+                if (yych <= 'E') {
+                    if (yych <= 'D') { gotoCase = 35; continue; };
+                    { gotoCase = 62; continue; };
+                } else {
+                    if (yych == 'e') { gotoCase = 62; continue; };
+                    { gotoCase = 35; continue; };
+                }
+            }
+case 37:
+            yych = this._charAt(++cursor);
+            if (yych <= ';') { gotoCase = 18; continue; };
+            if (yych <= '<') { gotoCase = 59; continue; };
+            if (yych <= '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 38:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 58; continue; };
+            { gotoCase = 18; continue; };
+case 39:
+            yych = this._charAt(++cursor);
+            if (yych <= '<') { gotoCase = 18; continue; };
+            if (yych <= '=') { gotoCase = 43; continue; };
+            if (yych <= '>') { gotoCase = 56; continue; };
+            { gotoCase = 18; continue; };
+case 40:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == 'u') { gotoCase = 44; continue; };
+            { gotoCase = 16; continue; };
+case 41:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 42:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            if (yych != '|') { gotoCase = 18; continue; };
+case 43:
+            yych = this._charAt(++cursor);
+            { gotoCase = 18; continue; };
+case 44:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 46; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 46; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 46; continue; };
+            }
+case 45:
+            cursor = YYMARKER;
+            if (yyaccept <= 1) {
+                if (yyaccept <= 0) {
+                    { gotoCase = 16; continue; };
+                } else {
+                    { gotoCase = 21; continue; };
+                }
+            } else {
+                if (yyaccept <= 2) {
+                    { gotoCase = 33; continue; };
+                } else {
+                    { gotoCase = 35; continue; };
+                }
+            }
+case 46:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 47; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 47:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 48; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 48:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 49; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 49:
+            yyaccept = 1;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 50:
+            if (yych <= '[') {
+                if (yych <= '/') {
+                    if (yych == '$') { gotoCase = 49; continue; };
+                    { gotoCase = 21; continue; };
+                } else {
+                    if (yych <= '9') { gotoCase = 49; continue; };
+                    if (yych <= '@') { gotoCase = 21; continue; };
+                    if (yych <= 'Z') { gotoCase = 49; continue; };
+                    { gotoCase = 21; continue; };
+                }
+            } else {
+                if (yych <= '_') {
+                    if (yych <= '\\') { gotoCase = 51; continue; };
+                    if (yych <= '^') { gotoCase = 21; continue; };
+                    { gotoCase = 49; continue; };
+                } else {
+                    if (yych <= '`') { gotoCase = 21; continue; };
+                    if (yych <= 'z') { gotoCase = 49; continue; };
+                    if (yych <= 0x7F) { gotoCase = 21; continue; };
+                    { gotoCase = 49; continue; };
+                }
+            }
+case 51:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych != 'u') { gotoCase = 45; continue; };
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 53; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 53:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 54; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 54:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 55; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 55:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 49; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 49; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 49; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 56:
+            yych = this._charAt(++cursor);
+            if (yych <= '<') { gotoCase = 18; continue; };
+            if (yych <= '=') { gotoCase = 43; continue; };
+            if (yych >= '?') { gotoCase = 18; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 58:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 59:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+case 60:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '9') {
+                if (yych == '.') { gotoCase = 63; continue; };
+                if (yych <= '/') { gotoCase = 35; continue; };
+                { gotoCase = 60; continue; };
+            } else {
+                if (yych <= 'E') {
+                    if (yych <= 'D') { gotoCase = 35; continue; };
+                } else {
+                    if (yych != 'e') { gotoCase = 35; continue; };
+                }
+            }
+case 62:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych == '+') { gotoCase = 69; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 69; continue; };
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 70; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 63:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'D') {
+                if (yych <= '/') { gotoCase = 35; continue; };
+                if (yych <= '9') { gotoCase = 63; continue; };
+                { gotoCase = 35; continue; };
+            } else {
+                if (yych <= 'E') { gotoCase = 65; continue; };
+                if (yych != 'e') { gotoCase = 35; continue; };
+            }
+case 65:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych != '+') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 66; continue; };
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 67; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 66:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 45; continue; };
+            if (yych >= ':') { gotoCase = 45; continue; };
+case 67:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 35; continue; };
+            if (yych <= '9') { gotoCase = 67; continue; };
+            { gotoCase = 35; continue; };
+case 69:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 45; continue; };
+            if (yych >= ':') { gotoCase = 45; continue; };
+case 70:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 35; continue; };
+            if (yych <= '9') { gotoCase = 70; continue; };
+            { gotoCase = 35; continue; };
+case 72:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 35; continue; };
+            if (yych <= '7') { gotoCase = 72; continue; };
+            { gotoCase = 35; continue; };
+case 74:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 75; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 75:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 35; continue; };
+                if (yych <= '9') { gotoCase = 75; continue; };
+                { gotoCase = 35; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 75; continue; };
+                if (yych <= '`') { gotoCase = 35; continue; };
+                if (yych <= 'f') { gotoCase = 75; continue; };
+                { gotoCase = 35; continue; };
+            }
+case 77:
+            yych = this._charAt(++cursor);
+            { gotoCase = 33; continue; };
+case 78:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 85; continue; };
+                { gotoCase = 78; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 85; continue; };
+                if (yych == '*') { gotoCase = 83; continue; };
+                { gotoCase = 78; continue; };
+            }
+case 80:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 82; continue; };
+            if (yych != '\r') { gotoCase = 80; continue; };
+case 82:
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 83:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '*') { gotoCase = 83; continue; };
+            if (yych == '/') { gotoCase = 87; continue; };
+            { gotoCase = 78; continue; };
+case 85:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.COMMENT);
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 87:
+            ++cursor;
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 89:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'D') {
+                if (yych <= '/') { gotoCase = 35; continue; };
+                if (yych <= '9') { gotoCase = 89; continue; };
+                { gotoCase = 35; continue; };
+            } else {
+                if (yych <= 'E') { gotoCase = 91; continue; };
+                if (yych != 'e') { gotoCase = 35; continue; };
+            }
+case 91:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych != '+') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 92; continue; };
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 93; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 92:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 45; continue; };
+            if (yych >= ':') { gotoCase = 45; continue; };
+case 93:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 35; continue; };
+            if (yych <= '9') { gotoCase = 93; continue; };
+            { gotoCase = 35; continue; };
+case 95:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 96:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 45; continue; };
+                if (yych <= '\f') { gotoCase = 95; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 95; continue; };
+                    { gotoCase = 98; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 95; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 45; continue; };
+                        { gotoCase = 101; continue; };
+                    } else {
+                        if (yych == '\r') { gotoCase = 101; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 95; continue; };
+                        if (yych <= '&') { gotoCase = 45; continue; };
+                        { gotoCase = 95; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 95; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 95; continue; };
+                        if (yych <= 'e') { gotoCase = 45; continue; };
+                        { gotoCase = 95; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 95; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 45; continue; };
+                        { gotoCase = 95; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 100; continue; };
+                        if (yych <= 'v') { gotoCase = 95; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                }
+            }
+case 98:
+            ++cursor;
+            { this.tokenType = "javascript-string"; return cursor; }
+case 100:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 103; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 103; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 103; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 101:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.SSTRING);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 103:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 104; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 104:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 105; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 105:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 95; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 95; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 95; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 106:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 107:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 45; continue; };
+                if (yych <= '\f') { gotoCase = 106; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 106; continue; };
+                    { gotoCase = 98; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 106; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 45; continue; };
+                        { gotoCase = 110; continue; };
+                    } else {
+                        if (yych == '\r') { gotoCase = 110; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 106; continue; };
+                        if (yych <= '&') { gotoCase = 45; continue; };
+                        { gotoCase = 106; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 106; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 106; continue; };
+                        if (yych <= 'e') { gotoCase = 45; continue; };
+                        { gotoCase = 106; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 106; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 45; continue; };
+                        { gotoCase = 106; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 109; continue; };
+                        if (yych <= 'v') { gotoCase = 106; continue; };
+                        { gotoCase = 45; continue; };
+                    }
+                }
+            }
+case 109:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 112; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 112; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 112; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 110:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DSTRING);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 112:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 113; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 113:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych >= ':') { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 114; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych >= 'g') { gotoCase = 45; continue; };
+            }
+case 114:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 45; continue; };
+                if (yych <= '9') { gotoCase = 106; continue; };
+                { gotoCase = 45; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 106; continue; };
+                if (yych <= '`') { gotoCase = 45; continue; };
+                if (yych <= 'f') { gotoCase = 106; continue; };
+                { gotoCase = 45; continue; };
+            }
+case 115:
+            ++cursor;
+            if ((yych = this._charAt(cursor)) == '=') { gotoCase = 43; continue; };
+            { gotoCase = 18; continue; };
+/* *********************************** */
+case this.case_DSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 120; continue; };
+                if (yych <= '\f') { gotoCase = 119; continue; };
+                { gotoCase = 120; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 119; continue; };
+                    { gotoCase = 122; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 124; continue; };
+                    { gotoCase = 119; continue; };
+                }
+            }
+case 118:
+            { this.tokenType = "javascript-string"; return cursor; }
+case 119:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 126; continue; };
+case 120:
+            ++cursor;
+case 121:
+            { this.tokenType = null; return cursor; }
+case 122:
+            ++cursor;
+case 123:
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 124:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 125; continue; };
+                    if (yych <= '&') { gotoCase = 121; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 121; continue; };
+                    } else {
+                        if (yych != 'b') { gotoCase = 121; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych >= 'g') { gotoCase = 121; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 125; continue; };
+                        if (yych <= 'q') { gotoCase = 121; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 121; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 127; continue; };
+                        if (yych >= 'w') { gotoCase = 121; continue; };
+                    }
+                }
+            }
+case 125:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 126:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 118; continue; };
+                if (yych <= '\f') { gotoCase = 125; continue; };
+                { gotoCase = 118; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 125; continue; };
+                    { gotoCase = 133; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 132; continue; };
+                    { gotoCase = 125; continue; };
+                }
+            }
+case 127:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 128; continue; };
+                if (yych <= '9') { gotoCase = 129; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 129; continue; };
+                if (yych <= '`') { gotoCase = 128; continue; };
+                if (yych <= 'f') { gotoCase = 129; continue; };
+            }
+case 128:
+            cursor = YYMARKER;
+            if (yyaccept <= 0) {
+                { gotoCase = 118; continue; };
+            } else {
+                { gotoCase = 121; continue; };
+            }
+case 129:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 128; continue; };
+                if (yych >= ':') { gotoCase = 128; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 130; continue; };
+                if (yych <= '`') { gotoCase = 128; continue; };
+                if (yych >= 'g') { gotoCase = 128; continue; };
+            }
+case 130:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 128; continue; };
+                if (yych >= ':') { gotoCase = 128; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 131; continue; };
+                if (yych <= '`') { gotoCase = 128; continue; };
+                if (yych >= 'g') { gotoCase = 128; continue; };
+            }
+case 131:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 128; continue; };
+                if (yych <= '9') { gotoCase = 125; continue; };
+                { gotoCase = 128; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 125; continue; };
+                if (yych <= '`') { gotoCase = 128; continue; };
+                if (yych <= 'f') { gotoCase = 125; continue; };
+                { gotoCase = 128; continue; };
+            }
+case 132:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 125; continue; };
+                    if (yych <= '&') { gotoCase = 128; continue; };
+                    { gotoCase = 125; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 128; continue; };
+                        { gotoCase = 125; continue; };
+                    } else {
+                        if (yych == 'b') { gotoCase = 125; continue; };
+                        { gotoCase = 128; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych <= 'f') { gotoCase = 125; continue; };
+                        { gotoCase = 128; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 125; continue; };
+                        if (yych <= 'q') { gotoCase = 128; continue; };
+                        { gotoCase = 125; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 128; continue; };
+                        { gotoCase = 125; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 127; continue; };
+                        if (yych <= 'v') { gotoCase = 125; continue; };
+                        { gotoCase = 128; continue; };
+                    }
+                }
+            }
+case 133:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 123; continue; };
+/* *********************************** */
+case this.case_NODIV:
+            yych = this._charAt(cursor);
+            if (yych <= '9') {
+                if (yych <= '(') {
+                    if (yych <= '#') {
+                        if (yych <= ' ') { gotoCase = 136; continue; };
+                        if (yych <= '!') { gotoCase = 138; continue; };
+                        if (yych <= '"') { gotoCase = 140; continue; };
+                    } else {
+                        if (yych <= '%') {
+                            if (yych <= '$') { gotoCase = 141; continue; };
+                            { gotoCase = 143; continue; };
+                        } else {
+                            if (yych <= '&') { gotoCase = 144; continue; };
+                            if (yych <= '\'') { gotoCase = 145; continue; };
+                            { gotoCase = 146; continue; };
+                        }
+                    }
+                } else {
+                    if (yych <= ',') {
+                        if (yych <= ')') { gotoCase = 147; continue; };
+                        if (yych <= '*') { gotoCase = 149; continue; };
+                        if (yych <= '+') { gotoCase = 150; continue; };
+                        { gotoCase = 146; continue; };
+                    } else {
+                        if (yych <= '.') {
+                            if (yych <= '-') { gotoCase = 151; continue; };
+                            { gotoCase = 152; continue; };
+                        } else {
+                            if (yych <= '/') { gotoCase = 153; continue; };
+                            if (yych <= '0') { gotoCase = 154; continue; };
+                            { gotoCase = 156; continue; };
+                        }
+                    }
+                }
+            } else {
+                if (yych <= '\\') {
+                    if (yych <= '>') {
+                        if (yych <= ';') { gotoCase = 146; continue; };
+                        if (yych <= '<') { gotoCase = 157; continue; };
+                        if (yych <= '=') { gotoCase = 158; continue; };
+                        { gotoCase = 159; continue; };
+                    } else {
+                        if (yych <= '@') {
+                            if (yych <= '?') { gotoCase = 146; continue; };
+                        } else {
+                            if (yych <= 'Z') { gotoCase = 141; continue; };
+                            if (yych <= '[') { gotoCase = 146; continue; };
+                            { gotoCase = 160; continue; };
+                        }
+                    }
+                } else {
+                    if (yych <= 'z') {
+                        if (yych <= '^') {
+                            if (yych <= ']') { gotoCase = 146; continue; };
+                            { gotoCase = 161; continue; };
+                        } else {
+                            if (yych != '`') { gotoCase = 141; continue; };
+                        }
+                    } else {
+                        if (yych <= '|') {
+                            if (yych <= '{') { gotoCase = 146; continue; };
+                            { gotoCase = 162; continue; };
+                        } else {
+                            if (yych <= '~') { gotoCase = 146; continue; };
+                            if (yych >= 0x80) { gotoCase = 141; continue; };
+                        }
+                    }
+                }
+            }
+case 136:
+            ++cursor;
+case 137:
+            { this.tokenType = null; return cursor; }
+case 138:
+            ++cursor;
+            if ((yych = this._charAt(cursor)) == '=') { gotoCase = 260; continue; };
+case 139:
+            { this.tokenType = null; return cursor; }
+case 140:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '\n') { gotoCase = 137; continue; };
+            if (yych == '\r') { gotoCase = 137; continue; };
+            { gotoCase = 252; continue; };
+case 141:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 170; continue; };
+case 142:
+            this.setLexCondition(this._lexConditions.DIV);
+            {
+                    var token = this._line.substring(cursorOnEnter, cursor);
+                    if (token in this._keywords)
+                        this.tokenType = "javascript-keyword";
+                    else
+                        this.tokenType = "javascript-ident";
+                    return cursor;
+                }
+case 143:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 144:
+            yych = this._charAt(++cursor);
+            if (yych == '&') { gotoCase = 163; continue; };
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 145:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == '\n') { gotoCase = 137; continue; };
+            if (yych == '\r') { gotoCase = 137; continue; };
+            { gotoCase = 241; continue; };
+case 146:
+            yych = this._charAt(++cursor);
+            { gotoCase = 139; continue; };
+case 147:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DIV);
+            { this.tokenType = null; return cursor; }
+case 149:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 150:
+            yych = this._charAt(++cursor);
+            if (yych == '+') { gotoCase = 163; continue; };
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 151:
+            yych = this._charAt(++cursor);
+            if (yych == '-') { gotoCase = 163; continue; };
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 152:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 139; continue; };
+            if (yych <= '9') { gotoCase = 234; continue; };
+            { gotoCase = 139; continue; };
+case 153:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 137; continue; };
+                    { gotoCase = 197; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 137; continue; };
+                    if (yych <= ')') { gotoCase = 197; continue; };
+                    { gotoCase = 202; continue; };
+                }
+            } else {
+                if (yych <= 'Z') {
+                    if (yych == '/') { gotoCase = 204; continue; };
+                    { gotoCase = 197; continue; };
+                } else {
+                    if (yych <= '[') { gotoCase = 200; continue; };
+                    if (yych <= '\\') { gotoCase = 199; continue; };
+                    if (yych <= ']') { gotoCase = 137; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            }
+case 154:
+            yyaccept = 2;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= 'E') {
+                if (yych <= '/') {
+                    if (yych == '.') { gotoCase = 183; continue; };
+                } else {
+                    if (yych <= '7') { gotoCase = 192; continue; };
+                    if (yych >= 'E') { gotoCase = 182; continue; };
+                }
+            } else {
+                if (yych <= 'd') {
+                    if (yych == 'X') { gotoCase = 194; continue; };
+                } else {
+                    if (yych <= 'e') { gotoCase = 182; continue; };
+                    if (yych == 'x') { gotoCase = 194; continue; };
+                }
+            }
+case 155:
+            this.setLexCondition(this._lexConditions.DIV);
+            { this.tokenType = "javascript-number"; return cursor; }
+case 156:
+            yyaccept = 2;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '9') {
+                if (yych == '.') { gotoCase = 183; continue; };
+                if (yych <= '/') { gotoCase = 155; continue; };
+                { gotoCase = 180; continue; };
+            } else {
+                if (yych <= 'E') {
+                    if (yych <= 'D') { gotoCase = 155; continue; };
+                    { gotoCase = 182; continue; };
+                } else {
+                    if (yych == 'e') { gotoCase = 182; continue; };
+                    { gotoCase = 155; continue; };
+                }
+            }
+case 157:
+            yych = this._charAt(++cursor);
+            if (yych <= ';') { gotoCase = 139; continue; };
+            if (yych <= '<') { gotoCase = 179; continue; };
+            if (yych <= '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 158:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 178; continue; };
+            { gotoCase = 139; continue; };
+case 159:
+            yych = this._charAt(++cursor);
+            if (yych <= '<') { gotoCase = 139; continue; };
+            if (yych <= '=') { gotoCase = 163; continue; };
+            if (yych <= '>') { gotoCase = 176; continue; };
+            { gotoCase = 139; continue; };
+case 160:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych == 'u') { gotoCase = 164; continue; };
+            { gotoCase = 137; continue; };
+case 161:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 162:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            if (yych != '|') { gotoCase = 139; continue; };
+case 163:
+            yych = this._charAt(++cursor);
+            { gotoCase = 139; continue; };
+case 164:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 166; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 166; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 166; continue; };
+            }
+case 165:
+            cursor = YYMARKER;
+            if (yyaccept <= 1) {
+                if (yyaccept <= 0) {
+                    { gotoCase = 137; continue; };
+                } else {
+                    { gotoCase = 142; continue; };
+                }
+            } else {
+                if (yyaccept <= 2) {
+                    { gotoCase = 155; continue; };
+                } else {
+                    { gotoCase = 217; continue; };
+                }
+            }
+case 166:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 167; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 167:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 168; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 168:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 169; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 169:
+            yyaccept = 1;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 170:
+            if (yych <= '[') {
+                if (yych <= '/') {
+                    if (yych == '$') { gotoCase = 169; continue; };
+                    { gotoCase = 142; continue; };
+                } else {
+                    if (yych <= '9') { gotoCase = 169; continue; };
+                    if (yych <= '@') { gotoCase = 142; continue; };
+                    if (yych <= 'Z') { gotoCase = 169; continue; };
+                    { gotoCase = 142; continue; };
+                }
+            } else {
+                if (yych <= '_') {
+                    if (yych <= '\\') { gotoCase = 171; continue; };
+                    if (yych <= '^') { gotoCase = 142; continue; };
+                    { gotoCase = 169; continue; };
+                } else {
+                    if (yych <= '`') { gotoCase = 142; continue; };
+                    if (yych <= 'z') { gotoCase = 169; continue; };
+                    if (yych <= 0x7F) { gotoCase = 142; continue; };
+                    { gotoCase = 169; continue; };
+                }
+            }
+case 171:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych != 'u') { gotoCase = 165; continue; };
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 173; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 173:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 174; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 174:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 175; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 175:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 169; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 169; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 169; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 176:
+            yych = this._charAt(++cursor);
+            if (yych <= '<') { gotoCase = 139; continue; };
+            if (yych <= '=') { gotoCase = 163; continue; };
+            if (yych >= '?') { gotoCase = 139; continue; };
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 178:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 179:
+            yych = this._charAt(++cursor);
+            if (yych == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+case 180:
+            yyaccept = 2;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '9') {
+                if (yych == '.') { gotoCase = 183; continue; };
+                if (yych <= '/') { gotoCase = 155; continue; };
+                { gotoCase = 180; continue; };
+            } else {
+                if (yych <= 'E') {
+                    if (yych <= 'D') { gotoCase = 155; continue; };
+                } else {
+                    if (yych != 'e') { gotoCase = 155; continue; };
+                }
+            }
+case 182:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych == '+') { gotoCase = 189; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 189; continue; };
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 190; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 183:
+            yyaccept = 2;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'D') {
+                if (yych <= '/') { gotoCase = 155; continue; };
+                if (yych <= '9') { gotoCase = 183; continue; };
+                { gotoCase = 155; continue; };
+            } else {
+                if (yych <= 'E') { gotoCase = 185; continue; };
+                if (yych != 'e') { gotoCase = 155; continue; };
+            }
+case 185:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych != '+') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 186; continue; };
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 187; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 186:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 165; continue; };
+            if (yych >= ':') { gotoCase = 165; continue; };
+case 187:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 155; continue; };
+            if (yych <= '9') { gotoCase = 187; continue; };
+            { gotoCase = 155; continue; };
+case 189:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 165; continue; };
+            if (yych >= ':') { gotoCase = 165; continue; };
+case 190:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 155; continue; };
+            if (yych <= '9') { gotoCase = 190; continue; };
+            { gotoCase = 155; continue; };
+case 192:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 155; continue; };
+            if (yych <= '7') { gotoCase = 192; continue; };
+            { gotoCase = 155; continue; };
+case 194:
+            yych = this._charAt(++cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 195; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 195:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 155; continue; };
+                if (yych <= '9') { gotoCase = 195; continue; };
+                { gotoCase = 155; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 195; continue; };
+                if (yych <= '`') { gotoCase = 155; continue; };
+                if (yych <= 'f') { gotoCase = 195; continue; };
+                { gotoCase = 155; continue; };
+            }
+case 197:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '.') {
+                if (yych <= '\n') {
+                    if (yych <= '\t') { gotoCase = 197; continue; };
+                    { gotoCase = 165; continue; };
+                } else {
+                    if (yych == '\r') { gotoCase = 165; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '/') { gotoCase = 220; continue; };
+                    if (yych <= 'Z') { gotoCase = 197; continue; };
+                    { gotoCase = 228; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 227; continue; };
+                    if (yych <= ']') { gotoCase = 165; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            }
+case 199:
+            yych = this._charAt(++cursor);
+            if (yych == '\n') { gotoCase = 165; continue; };
+            if (yych == '\r') { gotoCase = 165; continue; };
+            { gotoCase = 197; continue; };
+case 200:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 200; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 200; continue; };
+                    { gotoCase = 165; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych == '/') { gotoCase = 165; continue; };
+                    { gotoCase = 200; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 215; continue; };
+                    if (yych <= ']') { gotoCase = 213; continue; };
+                    { gotoCase = 200; continue; };
+                }
+            }
+case 202:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '\f') {
+                if (yych == '\n') { gotoCase = 209; continue; };
+                { gotoCase = 202; continue; };
+            } else {
+                if (yych <= '\r') { gotoCase = 209; continue; };
+                if (yych == '*') { gotoCase = 207; continue; };
+                { gotoCase = 202; continue; };
+            }
+case 204:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 206; continue; };
+            if (yych != '\r') { gotoCase = 204; continue; };
+case 206:
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 207:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '*') { gotoCase = 207; continue; };
+            if (yych == '/') { gotoCase = 211; continue; };
+            { gotoCase = 202; continue; };
+case 209:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.COMMENT);
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 211:
+            ++cursor;
+            { this.tokenType = "javascript-comment"; return cursor; }
+case 213:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 213; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 213; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            } else {
+                if (yych <= 'Z') {
+                    if (yych == '/') { gotoCase = 220; continue; };
+                    { gotoCase = 213; continue; };
+                } else {
+                    if (yych <= '[') { gotoCase = 218; continue; };
+                    if (yych <= '\\') { gotoCase = 216; continue; };
+                    { gotoCase = 213; continue; };
+                }
+            }
+case 215:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 165; continue; };
+            if (yych == '\r') { gotoCase = 165; continue; };
+            { gotoCase = 200; continue; };
+case 216:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 217; continue; };
+            if (yych != '\r') { gotoCase = 213; continue; };
+case 217:
+            this.setLexCondition(this._lexConditions.REGEX);
+            { this.tokenType = "javascript-regexp"; return cursor; }
+case 218:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 218; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 218; continue; };
+                    { gotoCase = 165; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych == '/') { gotoCase = 165; continue; };
+                    { gotoCase = 218; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 225; continue; };
+                    if (yych <= ']') { gotoCase = 223; continue; };
+                    { gotoCase = 218; continue; };
+                }
+            }
+case 220:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'h') {
+                if (yych == 'g') { gotoCase = 220; continue; };
+            } else {
+                if (yych <= 'i') { gotoCase = 220; continue; };
+                if (yych == 'm') { gotoCase = 220; continue; };
+            }
+            { this.tokenType = "javascript-regexp"; return cursor; }
+case 223:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 223; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 223; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            } else {
+                if (yych <= 'Z') {
+                    if (yych == '/') { gotoCase = 220; continue; };
+                    { gotoCase = 223; continue; };
+                } else {
+                    if (yych <= '[') { gotoCase = 218; continue; };
+                    if (yych <= '\\') { gotoCase = 226; continue; };
+                    { gotoCase = 223; continue; };
+                }
+            }
+case 225:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 165; continue; };
+            if (yych == '\r') { gotoCase = 165; continue; };
+            { gotoCase = 218; continue; };
+case 226:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 217; continue; };
+            if (yych == '\r') { gotoCase = 217; continue; };
+            { gotoCase = 223; continue; };
+case 227:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 217; continue; };
+            if (yych == '\r') { gotoCase = 217; continue; };
+            { gotoCase = 197; continue; };
+case 228:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 228; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 228; continue; };
+                    { gotoCase = 165; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych == '/') { gotoCase = 165; continue; };
+                    { gotoCase = 228; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 232; continue; };
+                    if (yych >= '^') { gotoCase = 228; continue; };
+                }
+            }
+case 230:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 165; continue; };
+                    { gotoCase = 230; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 165; continue; };
+                    if (yych <= ')') { gotoCase = 230; continue; };
+                    { gotoCase = 197; continue; };
+                }
+            } else {
+                if (yych <= 'Z') {
+                    if (yych == '/') { gotoCase = 220; continue; };
+                    { gotoCase = 230; continue; };
+                } else {
+                    if (yych <= '[') { gotoCase = 228; continue; };
+                    if (yych <= '\\') { gotoCase = 233; continue; };
+                    { gotoCase = 230; continue; };
+                }
+            }
+case 232:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 165; continue; };
+            if (yych == '\r') { gotoCase = 165; continue; };
+            { gotoCase = 228; continue; };
+case 233:
+            yyaccept = 3;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 217; continue; };
+            if (yych == '\r') { gotoCase = 217; continue; };
+            { gotoCase = 230; continue; };
+case 234:
+            yyaccept = 2;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'D') {
+                if (yych <= '/') { gotoCase = 155; continue; };
+                if (yych <= '9') { gotoCase = 234; continue; };
+                { gotoCase = 155; continue; };
+            } else {
+                if (yych <= 'E') { gotoCase = 236; continue; };
+                if (yych != 'e') { gotoCase = 155; continue; };
+            }
+case 236:
+            yych = this._charAt(++cursor);
+            if (yych <= ',') {
+                if (yych != '+') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= '-') { gotoCase = 237; continue; };
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 238; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 237:
+            yych = this._charAt(++cursor);
+            if (yych <= '/') { gotoCase = 165; continue; };
+            if (yych >= ':') { gotoCase = 165; continue; };
+case 238:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '/') { gotoCase = 155; continue; };
+            if (yych <= '9') { gotoCase = 238; continue; };
+            { gotoCase = 155; continue; };
+case 240:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 241:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 165; continue; };
+                if (yych <= '\f') { gotoCase = 240; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 240; continue; };
+                    { gotoCase = 243; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 240; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 165; continue; };
+                        { gotoCase = 246; continue; };
+                    } else {
+                        if (yych == '\r') { gotoCase = 246; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 240; continue; };
+                        if (yych <= '&') { gotoCase = 165; continue; };
+                        { gotoCase = 240; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 240; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 240; continue; };
+                        if (yych <= 'e') { gotoCase = 165; continue; };
+                        { gotoCase = 240; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 240; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 165; continue; };
+                        { gotoCase = 240; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 245; continue; };
+                        if (yych <= 'v') { gotoCase = 240; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                }
+            }
+case 243:
+            ++cursor;
+            { this.tokenType = "javascript-string"; return cursor; }
+case 245:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 248; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 248; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 248; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 246:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.SSTRING);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 248:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 249; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 249:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 250; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 250:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 240; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 240; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 240; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 251:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 252:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 165; continue; };
+                if (yych <= '\f') { gotoCase = 251; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= '"') {
+                    if (yych <= '!') { gotoCase = 251; continue; };
+                    { gotoCase = 243; continue; };
+                } else {
+                    if (yych != '\\') { gotoCase = 251; continue; };
+                }
+            }
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'a') {
+                if (yych <= '!') {
+                    if (yych <= '\n') {
+                        if (yych <= '\t') { gotoCase = 165; continue; };
+                        { gotoCase = 255; continue; };
+                    } else {
+                        if (yych == '\r') { gotoCase = 255; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                } else {
+                    if (yych <= '\'') {
+                        if (yych <= '"') { gotoCase = 251; continue; };
+                        if (yych <= '&') { gotoCase = 165; continue; };
+                        { gotoCase = 251; continue; };
+                    } else {
+                        if (yych == '\\') { gotoCase = 251; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'q') {
+                    if (yych <= 'f') {
+                        if (yych <= 'b') { gotoCase = 251; continue; };
+                        if (yych <= 'e') { gotoCase = 165; continue; };
+                        { gotoCase = 251; continue; };
+                    } else {
+                        if (yych == 'n') { gotoCase = 251; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych == 's') { gotoCase = 165; continue; };
+                        { gotoCase = 251; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 254; continue; };
+                        if (yych <= 'v') { gotoCase = 251; continue; };
+                        { gotoCase = 165; continue; };
+                    }
+                }
+            }
+case 254:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 257; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 257; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 257; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 255:
+            ++cursor;
+            this.setLexCondition(this._lexConditions.DSTRING);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 257:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 258; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 258:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych >= ':') { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 259; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych >= 'g') { gotoCase = 165; continue; };
+            }
+case 259:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 165; continue; };
+                if (yych <= '9') { gotoCase = 251; continue; };
+                { gotoCase = 165; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 251; continue; };
+                if (yych <= '`') { gotoCase = 165; continue; };
+                if (yych <= 'f') { gotoCase = 251; continue; };
+                { gotoCase = 165; continue; };
+            }
+case 260:
+            ++cursor;
+            if ((yych = this._charAt(cursor)) == '=') { gotoCase = 163; continue; };
+            { gotoCase = 139; continue; };
+/* *********************************** */
+case this.case_REGEX:
+            yych = this._charAt(cursor);
+            if (yych <= '.') {
+                if (yych <= '\n') {
+                    if (yych <= '\t') { gotoCase = 264; continue; };
+                    { gotoCase = 265; continue; };
+                } else {
+                    if (yych == '\r') { gotoCase = 265; continue; };
+                    { gotoCase = 264; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '/') { gotoCase = 267; continue; };
+                    if (yych <= 'Z') { gotoCase = 264; continue; };
+                    { gotoCase = 269; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 270; continue; };
+                    if (yych <= ']') { gotoCase = 265; continue; };
+                    { gotoCase = 264; continue; };
+                }
+            }
+case 263:
+            { this.tokenType = "javascript-regexp"; return cursor; }
+case 264:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 272; continue; };
+case 265:
+            ++cursor;
+case 266:
+            { this.tokenType = null; return cursor; }
+case 267:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 278; continue; };
+case 268:
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = "javascript-regexp"; return cursor; }
+case 269:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 266; continue; };
+                if (yych <= '\f') { gotoCase = 276; continue; };
+                { gotoCase = 266; continue; };
+            } else {
+                if (yych <= '*') {
+                    if (yych <= ')') { gotoCase = 276; continue; };
+                    { gotoCase = 266; continue; };
+                } else {
+                    if (yych == '/') { gotoCase = 266; continue; };
+                    { gotoCase = 276; continue; };
+                }
+            }
+case 270:
+            yych = this._charAt(++cursor);
+            if (yych == '\n') { gotoCase = 266; continue; };
+            if (yych == '\r') { gotoCase = 266; continue; };
+case 271:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 272:
+            if (yych <= '.') {
+                if (yych <= '\n') {
+                    if (yych <= '\t') { gotoCase = 271; continue; };
+                    { gotoCase = 263; continue; };
+                } else {
+                    if (yych == '\r') { gotoCase = 263; continue; };
+                    { gotoCase = 271; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych <= '/') { gotoCase = 277; continue; };
+                    if (yych <= 'Z') { gotoCase = 271; continue; };
+                    { gotoCase = 275; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 273; continue; };
+                    if (yych <= ']') { gotoCase = 263; continue; };
+                    { gotoCase = 271; continue; };
+                }
+            }
+case 273:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 274; continue; };
+            if (yych != '\r') { gotoCase = 271; continue; };
+case 274:
+            cursor = YYMARKER;
+            if (yyaccept <= 0) {
+                { gotoCase = 263; continue; };
+            } else {
+                { gotoCase = 266; continue; };
+            }
+case 275:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 276:
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 274; continue; };
+                    { gotoCase = 275; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 274; continue; };
+                    if (yych <= ')') { gotoCase = 275; continue; };
+                    { gotoCase = 274; continue; };
+                }
+            } else {
+                if (yych <= '[') {
+                    if (yych == '/') { gotoCase = 274; continue; };
+                    { gotoCase = 275; continue; };
+                } else {
+                    if (yych <= '\\') { gotoCase = 281; continue; };
+                    if (yych <= ']') { gotoCase = 279; continue; };
+                    { gotoCase = 275; continue; };
+                }
+            }
+case 277:
+            ++cursor;
+            yych = this._charAt(cursor);
+case 278:
+            if (yych <= 'h') {
+                if (yych == 'g') { gotoCase = 277; continue; };
+                { gotoCase = 268; continue; };
+            } else {
+                if (yych <= 'i') { gotoCase = 277; continue; };
+                if (yych == 'm') { gotoCase = 277; continue; };
+                { gotoCase = 268; continue; };
+            }
+case 279:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '*') {
+                if (yych <= '\f') {
+                    if (yych == '\n') { gotoCase = 263; continue; };
+                    { gotoCase = 279; continue; };
+                } else {
+                    if (yych <= '\r') { gotoCase = 263; continue; };
+                    if (yych <= ')') { gotoCase = 279; continue; };
+                    { gotoCase = 271; continue; };
+                }
+            } else {
+                if (yych <= 'Z') {
+                    if (yych == '/') { gotoCase = 277; continue; };
+                    { gotoCase = 279; continue; };
+                } else {
+                    if (yych <= '[') { gotoCase = 275; continue; };
+                    if (yych <= '\\') { gotoCase = 282; continue; };
+                    { gotoCase = 279; continue; };
+                }
+            }
+case 281:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 274; continue; };
+            if (yych == '\r') { gotoCase = 274; continue; };
+            { gotoCase = 275; continue; };
+case 282:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych == '\n') { gotoCase = 274; continue; };
+            if (yych == '\r') { gotoCase = 274; continue; };
+            { gotoCase = 279; continue; };
+/* *********************************** */
+case this.case_SSTRING:
+            yych = this._charAt(cursor);
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 287; continue; };
+                if (yych <= '\f') { gotoCase = 286; continue; };
+                { gotoCase = 287; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 286; continue; };
+                    { gotoCase = 289; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 291; continue; };
+                    { gotoCase = 286; continue; };
+                }
+            }
+case 285:
+            { this.tokenType = "javascript-string"; return cursor; }
+case 286:
+            yyaccept = 0;
+            yych = this._charAt(YYMARKER = ++cursor);
+            { gotoCase = 293; continue; };
+case 287:
+            ++cursor;
+case 288:
+            { this.tokenType = null; return cursor; }
+case 289:
+            ++cursor;
+case 290:
+            this.setLexCondition(this._lexConditions.NODIV);
+            { this.tokenType = "javascript-string"; return cursor; }
+case 291:
+            yyaccept = 1;
+            yych = this._charAt(YYMARKER = ++cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 292; continue; };
+                    if (yych <= '&') { gotoCase = 288; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 288; continue; };
+                    } else {
+                        if (yych != 'b') { gotoCase = 288; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych >= 'g') { gotoCase = 288; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 292; continue; };
+                        if (yych <= 'q') { gotoCase = 288; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 288; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 294; continue; };
+                        if (yych >= 'w') { gotoCase = 288; continue; };
+                    }
+                }
+            }
+case 292:
+            yyaccept = 0;
+            YYMARKER = ++cursor;
+            yych = this._charAt(cursor);
+case 293:
+            if (yych <= '\r') {
+                if (yych == '\n') { gotoCase = 285; continue; };
+                if (yych <= '\f') { gotoCase = 292; continue; };
+                { gotoCase = 285; continue; };
+            } else {
+                if (yych <= '\'') {
+                    if (yych <= '&') { gotoCase = 292; continue; };
+                    { gotoCase = 300; continue; };
+                } else {
+                    if (yych == '\\') { gotoCase = 299; continue; };
+                    { gotoCase = 292; continue; };
+                }
+            }
+case 294:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 295; continue; };
+                if (yych <= '9') { gotoCase = 296; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 296; continue; };
+                if (yych <= '`') { gotoCase = 295; continue; };
+                if (yych <= 'f') { gotoCase = 296; continue; };
+            }
+case 295:
+            cursor = YYMARKER;
+            if (yyaccept <= 0) {
+                { gotoCase = 285; continue; };
+            } else {
+                { gotoCase = 288; continue; };
+            }
+case 296:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 295; continue; };
+                if (yych >= ':') { gotoCase = 295; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 297; continue; };
+                if (yych <= '`') { gotoCase = 295; continue; };
+                if (yych >= 'g') { gotoCase = 295; continue; };
+            }
+case 297:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 295; continue; };
+                if (yych >= ':') { gotoCase = 295; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 298; continue; };
+                if (yych <= '`') { gotoCase = 295; continue; };
+                if (yych >= 'g') { gotoCase = 295; continue; };
+            }
+case 298:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= '@') {
+                if (yych <= '/') { gotoCase = 295; continue; };
+                if (yych <= '9') { gotoCase = 292; continue; };
+                { gotoCase = 295; continue; };
+            } else {
+                if (yych <= 'F') { gotoCase = 292; continue; };
+                if (yych <= '`') { gotoCase = 295; continue; };
+                if (yych <= 'f') { gotoCase = 292; continue; };
+                { gotoCase = 295; continue; };
+            }
+case 299:
+            ++cursor;
+            yych = this._charAt(cursor);
+            if (yych <= 'e') {
+                if (yych <= '\'') {
+                    if (yych == '"') { gotoCase = 292; continue; };
+                    if (yych <= '&') { gotoCase = 295; continue; };
+                    { gotoCase = 292; continue; };
+                } else {
+                    if (yych <= '\\') {
+                        if (yych <= '[') { gotoCase = 295; continue; };
+                        { gotoCase = 292; continue; };
+                    } else {
+                        if (yych == 'b') { gotoCase = 292; continue; };
+                        { gotoCase = 295; continue; };
+                    }
+                }
+            } else {
+                if (yych <= 'r') {
+                    if (yych <= 'm') {
+                        if (yych <= 'f') { gotoCase = 292; continue; };
+                        { gotoCase = 295; continue; };
+                    } else {
+                        if (yych <= 'n') { gotoCase = 292; continue; };
+                        if (yych <= 'q') { gotoCase = 295; continue; };
+                        { gotoCase = 292; continue; };
+                    }
+                } else {
+                    if (yych <= 't') {
+                        if (yych <= 's') { gotoCase = 295; continue; };
+                        { gotoCase = 292; continue; };
+                    } else {
+                        if (yych <= 'u') { gotoCase = 294; continue; };
+                        if (yych <= 'v') { gotoCase = 292; continue; };
+                        { gotoCase = 295; continue; };
+                    }
+                }
+            }
+case 300:
+            ++cursor;
+            yych = this._charAt(cursor);
+            { gotoCase = 290; continue; };
+        }
+
+        }
+    }
+}
+
+WebInspector.SourceJavaScriptTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js
new file mode 100644
index 0000000..ae71efe
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generate js file as follows:
+//
+// re2c -isc WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js \
+// | sed 's|^yy\([^:]*\)*\:|case \1:|' \
+// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \
+// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \
+// | sed 's|[*]cursor|this._charAt(cursor)|' \
+// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \
+// | sed 's|goto case \([^;]*\)|{ gotoCase = \1; continue; }|' \
+// | sed 's|unsigned\ int|var|' \
+// | sed 's|var\ yych|case 1: var yych|'
+
+WebInspector.SourceJavaScriptTokenizer = function()
+{
+    WebInspector.SourceTokenizer.call(this);
+
+    this._keywords = [
+        "null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for",
+        "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if",
+        "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger",
+        "class", "enum", "export", "extends", "import", "super", "get", "set", "with"
+    ].keySet();
+
+    this._lexConditions = {
+        DIV: 0,
+        NODIV: 1,
+        COMMENT: 2,
+        DSTRING: 3,
+        SSTRING: 4,
+        REGEX: 5
+    };
+
+    this.case_DIV = 1000;
+    this.case_NODIV = 1001;
+    this.case_COMMENT = 1002;
+    this.case_DSTRING = 1003;
+    this.case_SSTRING = 1004;
+    this.case_REGEX = 1005;
+
+    this.initialCondition = { lexCondition: this._lexConditions.NODIV }
+    this.condition = this.initialCondition;
+}
+
+WebInspector.SourceJavaScriptTokenizer.prototype = {
+    nextToken: function(cursor)
+    {
+        var cursorOnEnter = cursor;
+        var gotoCase = 1;
+        while (1) {
+            switch (gotoCase)
+            // Following comment is replaced with generated state machine.
+            /*!re2c
+                re2c:define:YYCTYPE  = "var";
+                re2c:define:YYCURSOR = cursor;
+                re2c:define:YYGETCONDITION = "this.getLexCondition";
+                re2c:define:YYSETCONDITION = "this.setLexCondition";
+                re2c:condprefix = "case this.case_";
+                re2c:condenumprefix = "this._lexConditions.";
+                re2c:yyfill:enable = 0;
+                re2c:labelprefix = "case ";
+                re2c:indent:top = 2;
+                re2c:indent:string = "    ";
+
+                LineComment = "//" [^\r\n]*;
+                CommentContent = ([^*\r\n] | ("*"+[^/*]))*;
+                Comment = "/*" CommentContent "*"+ "/";
+                CommentStart = "/*" CommentContent [\r\n];
+                CommentEnd = CommentContent "*"+ "/";
+
+                DecimalDigit = [0-9];
+                NonZeroDigit = [1-9];
+                OctalDigit = [0-7];
+                HexDigit = [0-9a-fA-F];
+                SignedInteger = ("+"|"-")? DecimalDigit+;
+                ExponentPart = ("e" | "E") SignedInteger;
+                DecimalIntegerLiteral = "0" | NonZeroDigit DecimalDigit*;
+                DecimalLiteral = DecimalIntegerLiteral "." DecimalDigit* ExponentPart? | "." DecimalDigit+ ExponentPart? | DecimalIntegerLiteral ExponentPart?;
+                HexIntegerLiteral = "0" ("x"|"X") HexDigit+;
+                OctalIntegerLiteral = "0" OctalDigit+;
+                NumericLiteral = DecimalLiteral | HexIntegerLiteral | OctalIntegerLiteral;
+
+                Punctuation = [\!\%\&\(\*\+\,\-\.\:\;\<\=\>\?\[\]\^\{\|\}\~] | "!=" | "!==" | "%=" | "&&" | "&=" | "*=" | "++" | "+=" | "--" | "-=" | "<<" | "<<="  | "<=" | "==" | "===" | ">=" | ">>" | ">>=" | ">>>" | ">>>=" | "^=" | "|=" | "||";
+                Division = "/" | "/=";
+                RightParen = ")";
+
+                Letter = [a-zA-Z\x80-\xFF];
+                UnicodeEscapeSequence = "\\u" HexDigit HexDigit HexDigit HexDigit;
+
+                IdentifierStart = Letter | "_" | "$" | UnicodeEscapeSequence;
+                IdentifierPart = IdentifierStart | DecimalDigit;
+                Identifier = IdentifierStart IdentifierPart *;
+
+                DoubleStringContent = ([^\r\n\"\\] | UnicodeEscapeSequence | "\\" ['"\\bfnrtv])*;
+                SingleStringContent = ([^\r\n\'\\] | UnicodeEscapeSequence | "\\" ['"\\bfnrtv])*;
+                StringLiteral = "\"" DoubleStringContent "\"" | "'" SingleStringContent "'";
+                DoubleStringStart = "\"" DoubleStringContent "\\" [\r\n];
+                DoubleStringEnd = DoubleStringContent "\"";
+                SingleStringStart = "'" SingleStringContent "\\" [\r\n];
+                SingleStringEnd = SingleStringContent "'";
+
+                BackslashSequence = "\\" [^\r\n];
+                RegexSet = "[" ([^\r\n*\\/] | BackslashSequence)* "]";
+                RegexFirstChar = [^\r\n*\\/\[\]] | BackslashSequence | RegexSet;
+                RegexChar = [^\r\n\\/\[\]] | BackslashSequence | RegexSet;
+                RegexContent = RegexChar*;
+                Regex = "/" RegexFirstChar RegexContent "/" [igm]*;
+                RegexStart = "/" RegexFirstChar RegexContent "\\";
+                RegexEnd = RegexContent "/" [igm]*;
+
+                <DIV,NODIV> LineComment { this.tokenType = "javascript-comment"; return cursor; }
+                <DIV,NODIV> Comment { this.tokenType = "javascript-comment"; return cursor; }
+                <DIV,NODIV> CommentStart => COMMENT { this.tokenType = "javascript-comment"; return cursor; }
+                <COMMENT> CommentContent => COMMENT { this.tokenType = "javascript-comment"; return cursor; }
+                <COMMENT> CommentEnd => NODIV { this.tokenType = "javascript-comment"; return cursor; }
+
+                <DIV,NODIV> StringLiteral { this.tokenType = "javascript-string"; return cursor; }
+                <DIV,NODIV> DoubleStringStart => DSTRING { this.tokenType = "javascript-string"; return cursor; }
+                <DSTRING> DoubleStringContent => DSTRING { this.tokenType = "javascript-string"; return cursor; }
+                <DSTRING> DoubleStringEnd => NODIV { this.tokenType = "javascript-string"; return cursor; }
+                <DIV,NODIV> SingleStringStart => SSTRING { this.tokenType = "javascript-string"; return cursor; }
+                <SSTRING> SingleStringContent => SSTRING { this.tokenType = "javascript-string"; return cursor; }
+                <SSTRING> SingleStringEnd => NODIV { this.tokenType = "javascript-string"; return cursor; }
+
+                <NODIV> Regex { this.tokenType = "javascript-regexp"; return cursor; }
+                <NODIV> RegexStart => REGEX { this.tokenType = "javascript-regexp"; return cursor; }
+                <REGEX> RegexContent => REGEX { this.tokenType = "javascript-regexp"; return cursor; }
+                <REGEX> RegexEnd => NODIV { this.tokenType = "javascript-regexp"; return cursor; }
+
+                <DIV,NODIV> NumericLiteral => DIV { this.tokenType = "javascript-number"; return cursor; }
+                <DIV,NODIV> Identifier => DIV
+                {
+                    var token = this._line.substring(cursorOnEnter, cursor);
+                    if (token in this._keywords)
+                        this.tokenType = "javascript-keyword";
+                    else
+                        this.tokenType = "javascript-ident";
+                    return cursor;
+                }
+                <DIV,NODIV> RightParen => DIV { this.tokenType = null; return cursor; }
+                <DIV,NODIV> Punctuation => NODIV { this.tokenType = null; return cursor; }
+                <DIV> Division => NODIV { this.tokenType = null; return cursor; }
+                <*> [^] { this.tokenType = null; return cursor; }
+            */
+        }
+    }
+}
+
+WebInspector.SourceJavaScriptTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceTokenizer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceTokenizer.js
new file mode 100644
index 0000000..d30744c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SourceTokenizer.js
@@ -0,0 +1,102 @@
+/* Generated by re2c 0.13.5 on Tue Jan 26 01:16:33 2010 */
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceTokenizer = function()
+{
+}
+
+WebInspector.SourceTokenizer.prototype = {
+    set line(line) {
+        this._line = line;
+    },
+
+    set condition(condition)
+    {
+        this._condition = condition;
+    },
+
+    get condition()
+    {
+        return this._condition;
+    },
+
+    get subTokenizer()
+    {
+        return this._condition.subTokenizer;
+    },
+
+    getLexCondition: function()
+    {
+        return this.condition.lexCondition;
+    },
+
+    setLexCondition: function(lexCondition)
+    {
+        this.condition.lexCondition = lexCondition;
+    },
+
+    _charAt: function(cursor)
+    {
+        return cursor < this._line.length ? this._line.charAt(cursor) : "\n";
+    }
+}
+
+
+WebInspector.SourceTokenizer.Registry = function() {
+    this._tokenizers = {};
+    this._tokenizerConstructors = {
+        "text/css": "SourceCSSTokenizer",
+        "text/html": "SourceHTMLTokenizer",
+        "text/javascript": "SourceJavaScriptTokenizer"
+    };
+}
+
+WebInspector.SourceTokenizer.Registry.getInstance = function()
+{
+    if (!WebInspector.SourceTokenizer.Registry._instance)
+        WebInspector.SourceTokenizer.Registry._instance = new WebInspector.SourceTokenizer.Registry();
+    return WebInspector.SourceTokenizer.Registry._instance;
+}
+
+WebInspector.SourceTokenizer.Registry.prototype = {
+    getTokenizer: function(mimeType)
+    {
+        if (!this._tokenizerConstructors[mimeType])
+            return null;
+        var tokenizerClass = this._tokenizerConstructors[mimeType];
+        var tokenizer = this._tokenizers[tokenizerClass];
+        if (!tokenizer) {
+            tokenizer = new WebInspector[tokenizerClass]();
+            this._tokenizers[mimeType] = tokenizer;
+        }
+        return tokenizer;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/StatusBarButton.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/StatusBarButton.js
new file mode 100644
index 0000000..e29b487
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/StatusBarButton.js
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.StatusBarButton = function(title, className, states)
+{
+    this.element = document.createElement("button");
+    this.element.className = className + " status-bar-item";
+    this.element.addEventListener("click", this._clicked.bind(this), false);
+
+    this.glyph = document.createElement("div");
+    this.glyph.className = "glyph";
+    this.element.appendChild(this.glyph);
+
+    this.glyphShadow = document.createElement("div");
+    this.glyphShadow.className = "glyph shadow";
+    this.element.appendChild(this.glyphShadow);
+    
+    this.states = states;
+    if (!states)
+        this.states = 2;
+
+    if (states == 2)
+        this._state = false;
+    else
+        this._state = 0;
+    
+    this.title = title;
+    this.disabled = false;
+    this._visible = true;
+}
+
+WebInspector.StatusBarButton.prototype = {
+    _clicked: function()
+    {
+        this.dispatchEventToListeners("click");
+    },
+
+    get disabled()
+    {
+        return this._disabled;
+    },
+
+    set disabled(x)
+    {
+        if (this._disabled === x)
+            return;
+        this._disabled = x;
+        this.element.disabled = x;
+    },
+
+    get title()
+    {
+        return this._title;
+    },
+
+    set title(x)
+    {
+        if (this._title === x)
+            return;
+        this._title = x;
+        this.element.title = x;
+    },
+    
+    get state()
+    {
+        return this._state;
+    },
+    
+    set state(x)
+    {
+        if (this._state === x)
+            return;
+        
+        if (this.states === 2) {
+            if (x)
+                this.element.addStyleClass("toggled-on");
+            else
+                this.element.removeStyleClass("toggled-on");
+        } else {
+            if (x !== 0) {
+                this.element.removeStyleClass("toggled-" + this._state);
+                this.element.addStyleClass("toggled-" + x);
+            } else 
+                this.element.removeStyleClass("toggled-" + this._state);
+        }
+        this._state = x;
+    },
+
+    get toggled()
+    {
+        if (this.states !== 2)
+            throw("Only used toggled when there are 2 states, otherwise, use state");
+        return this.state;
+    },
+
+    set toggled(x)
+    {
+        if (this.states !== 2)
+            throw("Only used toggled when there are 2 states, otherwise, use state");
+        this.state = x;
+    },
+
+    get visible()
+    {
+        return this._visible;
+    },
+
+    set visible(x)
+    {
+        if (this._visible === x)
+            return;
+
+        if (x)
+            this.element.removeStyleClass("hidden");
+        else
+            this.element.addStyleClass("hidden");
+        this._visible = x;
+    }
+}
+
+WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/StylesSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/StylesSidebarPane.js
new file mode 100644
index 0000000..57d3b76
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -0,0 +1,1975 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.StylesSidebarPane = function(computedStylePane)
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles"));
+
+    this.settingsSelectElement = document.createElement("select");
+
+    var option = document.createElement("option");
+    option.value = "original";
+    option.action = this._changeColorFormat.bind(this);
+    option.label = WebInspector.UIString("As Authored");
+    this.settingsSelectElement.appendChild(option);
+
+    var option = document.createElement("option");
+    option.value = "hex";
+    option.action = this._changeColorFormat.bind(this);
+    option.label = WebInspector.UIString("Hex Colors");
+    this.settingsSelectElement.appendChild(option);
+
+    option = document.createElement("option");
+    option.value = "rgb";
+    option.action = this._changeColorFormat.bind(this);
+    option.label = WebInspector.UIString("RGB Colors");
+    this.settingsSelectElement.appendChild(option);
+
+    option = document.createElement("option");
+    option.value = "hsl";
+    option.action = this._changeColorFormat.bind(this);
+    option.label = WebInspector.UIString("HSL Colors");
+    this.settingsSelectElement.appendChild(option);
+
+    this.settingsSelectElement.appendChild(document.createElement("hr"));
+
+    option = document.createElement("option");
+    option.action = this._createNewRule.bind(this);
+    option.label = WebInspector.UIString("New Style Rule");
+    this.settingsSelectElement.appendChild(option);
+
+    this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
+    this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
+    var format = WebInspector.settings.colorFormat;
+    if (format === "original")
+        this.settingsSelectElement[0].selected = true;
+    else if (format === "hex")
+        this.settingsSelectElement[1].selected = true;
+    else if (format === "rgb")
+        this.settingsSelectElement[2].selected = true;
+    else if (format === "hsl")
+        this.settingsSelectElement[3].selected = true;
+
+    this.titleElement.appendChild(this.settingsSelectElement);
+    this._computedStylePane = computedStylePane;
+    this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
+}
+
+WebInspector.StylesSidebarPane.StyleValueDelimiters = " \t\n\"':;,/()";
+
+// Taken from http://www.w3.org/TR/CSS21/propidx.html.
+WebInspector.StylesSidebarPane.InheritedProperties = [
+    "azimuth", "border-collapse", "border-spacing", "caption-side", "color", "cursor", "direction", "elevation",
+    "empty-cells", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "letter-spacing",
+    "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style", "orphans", "pitch-range",
+    "pitch", "quotes", "richness", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate", "stress",
+    "text-align", "text-indent", "text-transform", "text-shadow", "visibility", "voice-family", "volume", "white-space", "widows", "word-spacing"
+].keySet();
+
+// Keep in sync with RenderStyleConstants.h PseudoId enum. Array below contains pseudo id names for corresponding enum indexes.
+// First item is empty due to its artificial NOPSEUDO nature in the enum.
+// FIXME: find a way of generating this mapping or getting it from combination of RenderStyleConstants and CSSSelector.cpp at
+// runtime.
+WebInspector.StylesSidebarPane.PseudoIdNames = [
+    "", "first-line", "first-letter", "before", "after", "selection", "", "-webkit-scrollbar", "-webkit-file-upload-button",
+    "-webkit-input-placeholder", "-webkit-slider-thumb", "-webkit-search-cancel-button", "-webkit-search-decoration",
+    "-webkit-search-results-decoration", "-webkit-search-results-button", "-webkit-media-controls-panel",
+    "-webkit-media-controls-play-button", "-webkit-media-controls-mute-button", "-webkit-media-controls-timeline",
+    "-webkit-media-controls-timeline-container", "-webkit-media-controls-volume-slider",
+    "-webkit-media-controls-volume-slider-container", "-webkit-media-controls-current-time-display",
+    "-webkit-media-controls-time-remaining-display", "-webkit-media-controls-seek-back-button", "-webkit-media-controls-seek-forward-button",
+    "-webkit-media-controls-fullscreen-button", "-webkit-media-controls-rewind-button", "-webkit-media-controls-return-to-realtime-button",
+    "-webkit-media-controls-toggle-closed-captions-button", "-webkit-media-controls-status-display", "-webkit-scrollbar-thumb",
+    "-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece", "-webkit-scrollbar-corner",
+    "-webkit-resizer", "-webkit-input-list-button", "-webkit-inner-spin-button", "-webkit-outer-spin-button"
+];
+
+WebInspector.StylesSidebarPane.prototype = {
+    _contextMenuEventFired: function(event)
+    {
+        var href = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
+        if (href) {
+            var contextMenu = new WebInspector.ContextMenu();
+            var filled = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
+            if (filled)
+                contextMenu.show(event);
+        }
+    },
+
+    update: function(node, editedSection, forceUpdate)
+    {
+        var refresh = false;
+
+        if (forceUpdate)
+            delete this.node;
+
+        if (!forceUpdate && (!node || node === this.node))
+            refresh = true;
+
+        if (node && node.nodeType === Node.TEXT_NODE && node.parentNode)
+            node = node.parentNode;
+
+        if (node && node.nodeType !== Node.ELEMENT_NODE)
+            node = null;
+
+        if (node)
+            this.node = node;
+        else
+            node = this.node;
+
+        if (!node) {
+            this.bodyElement.removeChildren();
+            this._computedStylePane.bodyElement.removeChildren();
+            this.sections = {};
+            return;
+        }
+
+        function stylesCallback(styles)
+        {
+            if (styles)
+                this._rebuildUpdate(node, styles);
+        }
+
+        function computedStyleCallback(computedStyle)
+        {
+            if (computedStyle)
+                this._refreshUpdate(node, computedStyle, editedSection);
+        }
+
+        if (refresh)
+            WebInspector.cssModel.getComputedStyleAsync(node.id, computedStyleCallback.bind(this));
+        else
+            WebInspector.cssModel.getStylesAsync(node.id, stylesCallback.bind(this));
+    },
+
+    _refreshUpdate: function(node, computedStyle, editedSection)
+    {
+        for (var pseudoId in this.sections) {
+            var styleRules = this._refreshStyleRules(this.sections[pseudoId], computedStyle);
+            var usedProperties = {};
+            var disabledComputedProperties = {};
+            this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
+            this._refreshSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, editedSection);
+        }
+        // Trace the computed style.
+        this.sections[0][0].rebuildComputedTrace(this.sections[0]);
+    },
+
+    _rebuildUpdate: function(node, styles)
+    {
+        this.bodyElement.removeChildren();
+        this._computedStylePane.bodyElement.removeChildren();
+
+        var styleRules = this._rebuildStyleRules(node, styles);
+        var usedProperties = {};
+        var disabledComputedProperties = {};
+        this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
+        this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, 0);
+        var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement;
+        // Trace the computed style.
+        this.sections[0][0].rebuildComputedTrace(this.sections[0]);
+
+        for (var i = 0; i < styles.pseudoElements.length; ++i) {
+            var pseudoElementCSSRules = styles.pseudoElements[i];
+
+            styleRules = [];
+            var pseudoId = pseudoElementCSSRules.pseudoId;
+
+            var entry = { isStyleSeparator: true, pseudoId: pseudoId };
+            styleRules.push(entry);
+
+            // Add rules in reverse order to match the cascade order.
+            for (var j = pseudoElementCSSRules.rules.length - 1; j >= 0; --j) {
+                var rule = pseudoElementCSSRules.rules[j];
+                styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
+            }
+            usedProperties = {};
+            disabledComputedProperties = {};
+            this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
+            this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement);
+        }
+    },
+
+    _refreshStyleRules: function(sections, computedStyle)
+    {
+        var nodeComputedStyle = computedStyle;
+        var styleRules = [];
+        for (var i = 0; sections && i < sections.length; ++i) {
+            var section = sections[i];
+            if (section instanceof WebInspector.BlankStylePropertiesSection)
+                continue;
+            if (section.computedStyle)
+                section.styleRule.style = nodeComputedStyle;
+            var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule, editable: !!(section.styleRule.style && section.styleRule.style.id) };
+            styleRules.push(styleRule);
+        }
+        return styleRules;
+    },
+
+    _rebuildStyleRules: function(node, styles)
+    {
+        var nodeComputedStyle = styles.computedStyle;
+        this.sections = {};
+
+        var styleRules = [];
+
+        styleRules.push({ computedStyle: true, selectorText: "", style: nodeComputedStyle, editable: false });
+
+        var styleAttributes = {};
+        for (var name in styles.styleAttributes) {
+            var attrStyle = { style: styles.styleAttributes[name], editable: false };
+            attrStyle.selectorText = WebInspector.panels.elements.treeOutline.nodeNameToCorrectCase(node.nodeName) + "[" + name;
+            if (node.getAttribute(name))
+                attrStyle.selectorText += "=" + node.getAttribute(name);
+            attrStyle.selectorText += "]";
+            styleRules.push(attrStyle);
+        }
+
+        // Show element's Style Attributes
+        if (styles.inlineStyle && node.nodeType === Node.ELEMENT_NODE) {
+            var inlineStyle = { selectorText: "element.style", style: styles.inlineStyle, isAttribute: true };
+            styleRules.push(inlineStyle);
+        }
+
+        // Add rules in reverse order to match the cascade order.
+        if (styles.matchedCSSRules.length)
+            styleRules.push({ isStyleSeparator: true, text: WebInspector.UIString("Matched CSS Rules") });
+        for (var i = styles.matchedCSSRules.length - 1; i >= 0; --i) {
+            var rule = styles.matchedCSSRules[i];
+            styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
+        }
+
+        // Walk the node structure and identify styles with inherited properties.
+        var parentNode = node.parentNode;
+        function insertInheritedNodeSeparator(node)
+        {
+            var entry = {};
+            entry.isStyleSeparator = true;
+            entry.node = node;
+            styleRules.push(entry);
+        }
+
+        for (var parentOrdinal = 0; parentOrdinal < styles.inherited.length; ++parentOrdinal) {
+            var parentStyles = styles.inherited[parentOrdinal];
+            var separatorInserted = false;
+            if (parentStyles.inlineStyle) {
+                if (this._containsInherited(parentStyles.inlineStyle)) {
+                    var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true };
+                    if (!separatorInserted) {
+                        insertInheritedNodeSeparator(parentNode);
+                        separatorInserted = true;
+                    }
+                    styleRules.push(inlineStyle);
+                }
+            }
+
+            for (var i = parentStyles.matchedCSSRules.length - 1; i >= 0; --i) {
+                var rulePayload = parentStyles.matchedCSSRules[i];
+                if (!this._containsInherited(rulePayload.style))
+                    continue;
+                var rule = rulePayload;
+                if (!separatorInserted) {
+                    insertInheritedNodeSeparator(parentNode);
+                    separatorInserted = true;
+                }
+                styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, isInherited: true, editable: !!(rule.style && rule.style.id) });
+            }
+            parentNode = parentNode.parentNode;
+        }
+        return styleRules;
+    },
+
+    _markUsedProperties: function(styleRules, usedProperties, disabledComputedProperties)
+    {
+        var priorityUsed = false;
+
+        // Walk the style rules and make a list of all used and overloaded properties.
+        for (var i = 0; i < styleRules.length; ++i) {
+            var styleRule = styleRules[i];
+            if (styleRule.computedStyle || styleRule.isStyleSeparator)
+                continue;
+            if (styleRule.section && styleRule.section.noAffect)
+                continue;
+
+            styleRule.usedProperties = {};
+
+            var style = styleRule.style;
+            var allProperties = style.allProperties;
+            for (var j = 0; j < allProperties.length; ++j) {
+                var property = allProperties[j];
+                if (!property.isLive)
+                    continue;
+                var name = property.name;
+
+                if (!priorityUsed && property.priority.length)
+                    priorityUsed = true;
+
+                // If the property name is already used by another rule then this rule's
+                // property is overloaded, so don't add it to the rule's usedProperties.
+                if (!(name in usedProperties))
+                    styleRule.usedProperties[name] = true;
+
+                if (name === "font") {
+                    // The font property is not reported as a shorthand. Report finding the individual
+                    // properties so they are visible in computed style.
+                    // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15598 is fixed.
+                    styleRule.usedProperties["font-family"] = true;
+                    styleRule.usedProperties["font-size"] = true;
+                    styleRule.usedProperties["font-style"] = true;
+                    styleRule.usedProperties["font-variant"] = true;
+                    styleRule.usedProperties["font-weight"] = true;
+                    styleRule.usedProperties["line-height"] = true;
+                }
+            }
+
+            // Add all the properties found in this style to the used properties list.
+            // Do this here so only future rules are affect by properties used in this rule.
+            for (var name in styleRules[i].usedProperties)
+                usedProperties[name] = true;
+        }
+
+        if (priorityUsed) {
+            // Walk the properties again and account for !important.
+            var foundPriorityProperties = [];
+
+            // Walk in reverse to match the order !important overrides.
+            for (var i = (styleRules.length - 1); i >= 0; --i) {
+                if (styleRules[i].computedStyle || styleRules[i].isStyleSeparator)
+                    continue;
+
+                var style = styleRules[i].style;
+                var allProperties = style.allProperties;
+                for (var j = 0; j < allProperties.length; ++j) {
+                    var property = allProperties[j];
+                    if (!property.isLive)
+                        continue;
+                    var name = property.name;
+                    if (property.priority.length) {
+                        if (!(name in foundPriorityProperties))
+                            styleRules[i].usedProperties[name] = true;
+                        else
+                            delete styleRules[i].usedProperties[name];
+                        foundPriorityProperties[name] = true;
+                    } else if (name in foundPriorityProperties)
+                        delete styleRules[i].usedProperties[name];
+                }
+            }
+        }
+    },
+
+    _refreshSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, editedSection)
+    {
+        // Walk the style rules and update the sections with new overloaded and used properties.
+        for (var i = 0; i < styleRules.length; ++i) {
+            var styleRule = styleRules[i];
+            var section = styleRule.section;
+            if (styleRule.computedStyle) {
+                section._disabledComputedProperties = disabledComputedProperties;
+                section._usedProperties = usedProperties;
+                section.update();
+            } else {
+                section._usedProperties = styleRule.usedProperties;
+                section.update(section === editedSection);
+            }
+        }
+    },
+
+    _rebuildSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement)
+    {
+        // Make a property section for each style rule.
+        var sections = [];
+        var lastWasSeparator = true;
+        for (var i = 0; i < styleRules.length; ++i) {
+            var styleRule = styleRules[i];
+            if (styleRule.isStyleSeparator) {
+                var separatorElement = document.createElement("div");
+                separatorElement.className = "styles-sidebar-separator";
+                if (styleRule.node) {
+                    var link = WebInspector.panels.elements.linkifyNodeReference(styleRule.node);
+                    separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " "));
+                    separatorElement.appendChild(link);
+                    if (!sections.inheritedPropertiesSeparatorElement)
+                        sections.inheritedPropertiesSeparatorElement = separatorElement;
+                } else if ("pseudoId" in styleRule) {
+                    var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[styleRule.pseudoId];
+                    if (pseudoName)
+                        separatorElement.textContent = WebInspector.UIString("Pseudo ::%s element", pseudoName);
+                    else
+                        separatorElement.textContent = WebInspector.UIString("Pseudo element");
+                } else
+                    separatorElement.textContent = styleRule.text;
+                this.bodyElement.insertBefore(separatorElement, anchorElement);
+                lastWasSeparator = true;
+                continue;
+            }
+            var computedStyle = styleRule.computedStyle;
+
+            // Default editable to true if it was omitted.
+            var editable = styleRule.editable;
+            if (typeof editable === "undefined")
+                editable = true;
+
+            if (computedStyle)
+                var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties, disabledComputedProperties, styleRules);
+            else
+                var section = new WebInspector.StylePropertiesSection(styleRule, editable, styleRule.isInherited, lastWasSeparator);
+            section.pane = this;
+            section.expanded = true;
+
+            if (computedStyle) {
+                this._computedStylePane.bodyElement.appendChild(section.element);
+                lastWasSeparator = true;
+            } else {
+                this.bodyElement.insertBefore(section.element, anchorElement);
+                lastWasSeparator = false;
+            }
+            sections.push(section);
+        }
+        return sections;
+    },
+
+    _containsInherited: function(style)
+    {
+        var properties = style.allProperties;
+        for (var i = 0; i < properties.length; ++i) {
+            var property = properties[i];
+            // Does this style contain non-overridden inherited property?
+            if (property.isLive && property.name in WebInspector.StylesSidebarPane.InheritedProperties)
+                return true;
+        }
+        return false;
+    },
+
+    _changeSetting: function(event)
+    {
+        var options = this.settingsSelectElement.options;
+        var selectedOption = options[this.settingsSelectElement.selectedIndex];
+        selectedOption.action(event);
+
+        // Select the correct color format setting again, since it needs to be selected.
+        var selectedIndex = 0;
+        for (var i = 0; i < options.length; ++i) {
+            if (options[i].value === WebInspector.settings.colorFormat) {
+                selectedIndex = i;
+                break;
+            }
+        }
+
+        this.settingsSelectElement.selectedIndex = selectedIndex;
+    },
+
+    _changeColorFormat: function(event)
+    {
+        var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
+        WebInspector.settings.colorFormat = selectedOption.value;
+
+        for (var pseudoId in this.sections) {
+            var sections = this.sections[pseudoId];
+            for (var i = 0; i < sections.length; ++i)
+                sections[i].update(true);
+        }
+    },
+
+    _createNewRule: function(event)
+    {
+        this.addBlankSection().startEditingSelector();
+    },
+
+    addBlankSection: function()
+    {
+        var blankSection = new WebInspector.BlankStylePropertiesSection(appropriateSelectorForNode(this.node, true));
+        blankSection.pane = this;
+
+        var elementStyleSection = this.sections[0][1];
+        this.bodyElement.insertBefore(blankSection.element, elementStyleSection.element.nextSibling);
+
+        this.sections[0].splice(2, 0, blankSection);
+
+        return blankSection;
+    },
+
+    removeSection: function(section)
+    {
+        for (var pseudoId in this.sections) {
+            var sections = this.sections[pseudoId];
+            var index = sections.indexOf(section);
+            if (index === -1)
+                continue;
+            sections.splice(index, 1);
+            if (section.element.parentNode)
+                section.element.parentNode.removeChild(section.element);
+        }
+    },
+
+    registerShortcuts: function()
+    {
+        var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Styles Pane"));
+        var shortcut = WebInspector.KeyboardShortcut;
+        var keys = [
+            shortcut.shortcutToString(shortcut.Keys.Tab),
+            shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Next/previous property"));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.Up),
+            shortcut.shortcutToString(shortcut.Keys.Down)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement value"));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.Up, shortcut.Modifiers.Shift),
+            shortcut.shortcutToString(shortcut.Keys.Down, shortcut.Modifiers.Shift)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.PageUp),
+            shortcut.shortcutToString(shortcut.Keys.PageDown)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Shift),
+            shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Shift)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 100));
+        keys = [
+            shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Alt),
+            shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Alt)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 0.1));
+    }
+}
+
+WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.ComputedStyleSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Computed Style"));
+    var showInheritedCheckbox = new WebInspector.Checkbox(WebInspector.UIString("Show inherited"), "sidebar-pane-subtitle");
+    this.titleElement.appendChild(showInheritedCheckbox.element);
+
+    if (WebInspector.settings.showInheritedComputedStyleProperties) {
+        this.bodyElement.addStyleClass("show-inherited");
+        showInheritedCheckbox.checked = true;
+    }
+
+    function showInheritedToggleFunction(event)
+    {
+        WebInspector.settings.showInheritedComputedStyleProperties = showInheritedCheckbox.checked;
+        if (WebInspector.settings.showInheritedComputedStyleProperties)
+            this.bodyElement.addStyleClass("show-inherited");
+        else
+            this.bodyElement.removeStyleClass("show-inherited");
+    }
+
+    showInheritedCheckbox.addEventListener(showInheritedToggleFunction.bind(this));
+}
+
+WebInspector.ComputedStyleSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.StylePropertiesSection = function(styleRule, editable, isInherited, isFirstSection)
+{
+    WebInspector.PropertiesSection.call(this, "");
+    this.element.className = "styles-section monospace" + (isFirstSection ? " first-styles-section" : "");
+
+    this._selectorElement = document.createElement("span");
+    this._selectorElement.textContent = styleRule.selectorText;
+    this.titleElement.appendChild(this._selectorElement);
+    if (Preferences.debugMode)
+        this._selectorElement.addEventListener("click", this._debugShowStyle.bind(this), false);
+
+    var openBrace = document.createElement("span");
+    openBrace.textContent = " {";
+    this.titleElement.appendChild(openBrace);
+
+    var closeBrace = document.createElement("div");
+    closeBrace.textContent = "}";
+    this.element.appendChild(closeBrace);
+
+    this._selectorElement.addEventListener("dblclick", this._handleSelectorDoubleClick.bind(this), false);
+    this.element.addEventListener("dblclick", this._handleEmptySpaceDoubleClick.bind(this), false);
+
+    this.styleRule = styleRule;
+    this.rule = this.styleRule.rule;
+    this.editable = editable;
+    this.isInherited = isInherited;
+
+    // Prevent editing the user agent and user rules.
+    var isUserAgent = this.rule && this.rule.isUserAgent;
+    var isUser = this.rule && this.rule.isUser;
+    var isViaInspector = this.rule && this.rule.isViaInspector;
+
+    if (isUserAgent || isUser)
+        this.editable = false;
+
+    this._usedProperties = styleRule.usedProperties;
+
+    if (this.rule)
+        this.titleElement.addStyleClass("styles-selector");
+
+    function linkifyUncopyable(url, line)
+    {
+        var link = WebInspector.linkifyResourceAsNode(url, "resources", line + 1);
+        link.setAttribute("data-uncopyable", link.textContent);
+        link.textContent = "";
+        return link;
+    }
+
+    var subtitle = "";
+    if (this.styleRule.sourceURL)
+        this.subtitleElement.appendChild(linkifyUncopyable(this.styleRule.sourceURL, this.rule.sourceLine));
+    else if (isUserAgent)
+        subtitle = WebInspector.UIString("user agent stylesheet");
+    else if (isUser)
+        subtitle = WebInspector.UIString("user stylesheet");
+    else if (isViaInspector)
+        subtitle = WebInspector.UIString("via inspector");
+    else if (this.rule && this.rule.sourceURL)
+        this.subtitleElement.appendChild(linkifyUncopyable(this.rule.sourceURL, this.rule.sourceLine));
+
+    if (isInherited)
+        this.element.addStyleClass("show-inherited"); // This one is related to inherited rules, not compted style.
+    if (subtitle)
+        this.subtitle = subtitle;
+
+    this.identifier = styleRule.selectorText;
+    if (this.subtitle)
+        this.identifier += ":" + this.subtitle;
+
+    if (!this.editable)
+        this.element.addStyleClass("read-only");
+}
+
+WebInspector.StylePropertiesSection.prototype = {
+    collapse: function(dontRememberState)
+    {
+        // Overriding with empty body.
+    },
+
+    isPropertyInherited: function(propertyName)
+    {
+        if (this.isInherited) {
+            // While rendering inherited stylesheet, reverse meaning of this property.
+            // Render truly inherited properties with black, i.e. return them as non-inherited.
+            return !(propertyName in WebInspector.StylesSidebarPane.InheritedProperties);
+        }
+        return false;
+    },
+
+    isPropertyOverloaded: function(propertyName, shorthand)
+    {
+        if (!this._usedProperties || this.noAffect)
+            return false;
+
+        if (this.isInherited && !(propertyName in WebInspector.StylesSidebarPane.InheritedProperties)) {
+            // In the inherited sections, only show overrides for the potentially inherited properties.
+            return false;
+        }
+
+        var used = (propertyName in this._usedProperties);
+        if (used || !shorthand)
+            return !used;
+
+        // Find out if any of the individual longhand properties of the shorthand
+        // are used, if none are then the shorthand is overloaded too.
+        var longhandProperties = this.styleRule.style.getLonghandProperties(propertyName);
+        for (var j = 0; j < longhandProperties.length; ++j) {
+            var individualProperty = longhandProperties[j];
+            if (individualProperty.name in this._usedProperties)
+                return false;
+        }
+
+        return true;
+    },
+
+    nextEditableSibling: function()
+    {
+        var curSection = this;
+        do {
+            curSection = curSection.nextSibling;
+        } while (curSection && !curSection.editable);
+
+        return curSection;
+    },
+
+    previousEditableSibling: function()
+    {
+        var curSection = this;
+        do {
+            curSection = curSection.previousSibling;
+        } while (curSection && !curSection.editable);
+
+        return curSection;
+    },
+
+    update: function(full)
+    {
+        if (full) {
+            this.propertiesTreeOutline.removeChildren();
+            this.populated = false;
+        } else {
+            var child = this.propertiesTreeOutline.children[0];
+            while (child) {
+                child.overloaded = this.isPropertyOverloaded(child.name, child.shorthand);
+                child = child.traverseNextTreeElement(false, null, true);
+            }
+        }
+        this.afterUpdate();
+    },
+
+    afterUpdate: function()
+    {
+        if (this._afterUpdate) {
+            this._afterUpdate(this);
+            delete this._afterUpdate;
+        }
+    },
+
+    onpopulate: function()
+    {
+        var style = this.styleRule.style;
+
+        var handledProperties = {};
+        var shorthandNames = {};
+
+        this.uniqueProperties = [];
+        var allProperties = style.allProperties;
+        for (var i = 0; i < allProperties.length; ++i)
+            this.uniqueProperties.push(allProperties[i]);
+
+        // Collect all shorthand names.
+        for (var i = 0; i < this.uniqueProperties.length; ++i) {
+            var property = this.uniqueProperties[i];
+            if (property.disabled)
+                continue;
+            if (property.shorthand)
+                shorthandNames[property.shorthand] = true;
+        }
+
+        // Collect all shorthand names.
+        for (var i = 0; i < this.uniqueProperties.length; ++i) {
+            var property = this.uniqueProperties[i];
+            var disabled = property.disabled;
+            if (!disabled && this.disabledComputedProperties && !(property.name in this.usedProperties) && property.name in this.disabledComputedProperties)
+                disabled = true;
+
+            var shorthand = !disabled ? property.shorthand : null;
+
+            if (shorthand && shorthand in handledProperties)
+                continue;
+
+            if (shorthand) {
+                property = style.getLiveProperty(shorthand);
+                if (!property)
+                    property = new WebInspector.CSSProperty(style, style.allProperties.length, shorthand, style.getShorthandValue(shorthand), style.getShorthandPriority(shorthand), "style", true, true, "");
+            }
+
+            var isShorthand = !!(property.isLive && (shorthand || shorthandNames[property.name]));
+            var inherited = this.isPropertyInherited(property.name);
+            var overloaded = this.isPropertyOverloaded(property.name, isShorthand);
+
+            var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, isShorthand, inherited, overloaded);
+            this.propertiesTreeOutline.appendChild(item);
+            handledProperties[property.name] = property;
+        }
+    },
+
+    findTreeElementWithName: function(name)
+    {
+        var treeElement = this.propertiesTreeOutline.children[0];
+        while (treeElement) {
+            if (treeElement.name === name)
+                return treeElement;
+            treeElement = treeElement.traverseNextTreeElement(true, null, true);
+        }
+        return null;
+    },
+
+    addNewBlankProperty: function(optionalIndex)
+    {
+        var style = this.styleRule.style;
+        var property = style.newBlankProperty();
+        var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, false, false);
+        this.propertiesTreeOutline.appendChild(item);
+        item.listItemElement.textContent = "";
+        item._newProperty = true;
+        item.updateTitle();
+        return item;
+    },
+
+    _debugShowStyle: function(anchor)
+    {
+        var boundHandler;
+        function removeStyleBox(element, event)
+        {
+            if (event.target === element) {
+                event.stopPropagation();
+                return;
+            }
+            document.body.removeChild(element);
+            document.getElementById("main").removeEventListener("mousedown", boundHandler, true);
+        }
+
+        if (!event.shiftKey)
+            return;
+
+        var container = document.createElement("div");
+        var element = document.createElement("span");
+        container.appendChild(element);
+        element.style.background = "yellow";
+        element.style.display = "inline-block";
+        container.style.cssText = "z-index: 2000000; position: absolute; top: 50px; left: 50px; white-space: pre; overflow: auto; background: white; font-family: monospace; font-size: 12px; border: 1px solid black; opacity: 0.85; -webkit-user-select: text; padding: 2px;";
+        container.style.width = (document.body.offsetWidth - 100) + "px";
+        container.style.height = (document.body.offsetHeight - 100) + "px";
+        document.body.appendChild(container);
+        if (this.rule)
+            element.textContent = this.rule.selectorText + " {" + ((this.styleRule.style.cssText !== undefined) ? this.styleRule.style.cssText : "<no cssText>") + "}";
+        else
+            element.textContent = this.styleRule.style.cssText;
+        boundHandler = removeStyleBox.bind(null, container);
+        document.getElementById("main").addEventListener("mousedown", boundHandler, true);
+    },
+
+    _handleEmptySpaceDoubleClick: function(event)
+    {
+        if (event.target.hasStyleClass("header")) {
+            event.stopPropagation();
+            return;
+        }
+        this.expand();
+        this.addNewBlankProperty().startEditing();
+    },
+
+    _handleSelectorClick: function(event)
+    {
+        event.stopPropagation();
+    },
+
+    _handleSelectorDoubleClick: function(event)
+    {
+        this._startEditingOnMouseEvent();
+        event.stopPropagation();
+    },
+
+    _startEditingOnMouseEvent: function()
+    {
+        if (!this.editable)
+            return;
+
+        if (!this.rule && this.propertiesTreeOutline.children.length === 0) {
+            this.expand();
+            this.addNewBlankProperty().startEditing();
+            return;
+        }
+
+        if (!this.rule)
+            return;
+
+        this.startEditingSelector();
+    },
+
+    startEditingSelector: function()
+    {
+        var element = this._selectorElement;
+        if (WebInspector.isBeingEdited(element))
+            return;
+
+        WebInspector.startEditing(this._selectorElement, {
+            context: null,
+            commitHandler: this.editingSelectorCommitted.bind(this),
+            cancelHandler: this.editingSelectorCancelled.bind(this)
+        });
+        window.getSelection().setBaseAndExtent(element, 0, element, 1);
+    },
+
+    editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
+    {
+        function moveToNextIfNeeded() {
+            if (!moveDirection)
+                return;
+
+            if (moveDirection === "forward") {
+                this.expand();
+                if (this.propertiesTreeOutline.children.length === 0)
+                    this.addNewBlankProperty().startEditing();
+                else {
+                    var item = this.propertiesTreeOutline.children[0]
+                    item.startEditing(item.nameElement);
+                }
+            } else {
+                var previousSection = this.previousEditableSibling();
+                if (!previousSection)
+                    return;
+
+                previousSection.expand();
+                previousSection.addNewBlankProperty().startEditing();
+            }
+        }
+
+        if (newContent === oldContent)
+            return moveToNextIfNeeded.call(this);
+
+        var self = this;
+
+        function successCallback(newRule, doesAffectSelectedNode)
+        {
+            if (!doesAffectSelectedNode) {
+                self.noAffect = true;
+                self.element.addStyleClass("no-affect");
+            } else {
+                delete self.noAffect;
+                self.element.removeStyleClass("no-affect");
+            }
+
+            self.rule = newRule;
+            self.styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule };
+
+            var oldIdentifier = this.identifier;
+            self.identifier = newRule.selectorText + ":" + self.subtitleElement.textContent;
+
+            self.pane.update();
+
+            WebInspector.panels.elements.renameSelector(oldIdentifier, this.identifier, oldContent, newContent);
+
+            moveToNextIfNeeded.call(self);
+        }
+
+        var focusedNode = WebInspector.panels.elements.focusedDOMNode;
+        WebInspector.cssModel.setRuleSelector(this.rule.id, focusedNode ? focusedNode.id : 0, newContent, successCallback, moveToNextIfNeeded.bind(this));
+    },
+
+    editingSelectorCancelled: function()
+    {
+        // Do nothing, this is overridden by BlankStylePropertiesSection.
+    }
+}
+
+WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.ComputedStylePropertiesSection = function(styleRule, usedProperties, disabledComputedProperties)
+{
+    WebInspector.PropertiesSection.call(this, "");
+    this.headerElement.addStyleClass("hidden");
+    this.element.className = "styles-section monospace first-styles-section read-only computed-style";
+    this.styleRule = styleRule;
+    this._usedProperties = usedProperties;
+    this._disabledComputedProperties = disabledComputedProperties;
+    this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
+    this.computedStyle = true;
+    this._propertyTreeElements = {};
+    this._expandedPropertyNames = {};
+}
+
+WebInspector.ComputedStylePropertiesSection.prototype = {
+    collapse: function(dontRememberState)
+    {
+        // Overriding with empty body.
+    },
+
+    _isPropertyInherited: function(propertyName)
+    {
+        return !(propertyName in this._usedProperties) && !(propertyName in this._alwaysShowComputedProperties) && !(propertyName in this._disabledComputedProperties);
+    },
+
+    update: function()
+    {
+        this._expandedPropertyNames = {};
+        for (var name in this._propertyTreeElements) {
+            if (this._propertyTreeElements[name].expanded)
+                this._expandedPropertyNames[name] = true;
+        }
+        this._propertyTreeElements = {};
+        this.propertiesTreeOutline.removeChildren();
+        this.populated = false;
+    },
+
+    onpopulate: function()
+    {
+        function sorter(a, b)
+        {
+            return a.name.localeCompare(b.name);
+        }
+
+        var style = this.styleRule.style;
+        var uniqueProperties = [];
+        var allProperties = style.allProperties;
+        for (var i = 0; i < allProperties.length; ++i)
+            uniqueProperties.push(allProperties[i]);
+        uniqueProperties.sort(sorter);
+
+        this._propertyTreeElements = {};
+        for (var i = 0; i < uniqueProperties.length; ++i) {
+            var property = uniqueProperties[i];
+            var inherited = this._isPropertyInherited(property.name);
+            var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, inherited, false);
+            this.propertiesTreeOutline.appendChild(item);
+            this._propertyTreeElements[property.name] = item;
+        }
+    },
+
+    rebuildComputedTrace: function(sections)
+    {
+        for (var i = 0; i < sections.length; ++i) {
+            var section = sections[i];
+            if (section.computedStyle || section instanceof WebInspector.BlankStylePropertiesSection)
+                continue;
+
+            for (var j = 0; j < section.uniqueProperties.length; ++j) {
+                var property = section.uniqueProperties[j];
+                if (property.disabled)
+                    continue;
+                if (section.isInherited && !(property.name in WebInspector.StylesSidebarPane.InheritedProperties))
+                    continue;
+
+                var treeElement = this._propertyTreeElements[property.name];
+                if (treeElement) {
+                    var selectorText = section.styleRule.selectorText;
+                    var value = property.value;
+                    var title = "<span style='color: gray'>" + selectorText + "</span> - " + value;
+                    var subtitle = " <span style='float:right'>" + section.subtitleElement.innerHTML + "</span>";
+                    var childElement = new TreeElement(null, null, false);
+                    childElement.titleHTML = title + subtitle;
+                    treeElement.appendChild(childElement);
+                    if (section.isPropertyOverloaded(property.name))
+                        childElement.listItemElement.addStyleClass("overloaded");
+                }
+            }
+        }
+
+        // Restore expanded state after update.
+        for (var name in this._expandedPropertyNames) {
+            if (name in this._propertyTreeElements)
+                this._propertyTreeElements[name].expand();
+        }
+    }
+}
+
+WebInspector.ComputedStylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.BlankStylePropertiesSection = function(defaultSelectorText)
+{
+    WebInspector.StylePropertiesSection.call(this, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
+    this.element.addStyleClass("blank-section");
+}
+
+WebInspector.BlankStylePropertiesSection.prototype = {
+    expand: function()
+    {
+        // Do nothing, blank sections are not expandable.
+    },
+
+    editingSelectorCommitted: function(element, newContent, oldContent, context)
+    {
+        var self = this;
+        function successCallback(newRule, doesSelectorAffectSelectedNode)
+        {
+            var styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule };
+            self.makeNormal(styleRule);
+
+            if (!doesSelectorAffectSelectedNode) {
+                self.noAffect = true;
+                self.element.addStyleClass("no-affect");
+            }
+
+            self.subtitleElement.textContent = WebInspector.UIString("via inspector");
+            self.expand();
+
+            self.addNewBlankProperty().startEditing();
+        }
+
+        WebInspector.cssModel.addRule(this.pane.node.id, newContent, successCallback, this.editingSelectorCancelled.bind(this));
+    },
+
+    editingSelectorCancelled: function()
+    {
+        this.pane.removeSection(this);
+    },
+
+    makeNormal: function(styleRule)
+    {
+        this.element.removeStyleClass("blank-section");
+        this.styleRule = styleRule;
+        this.rule = styleRule.rule;
+        this.identifier = styleRule.selectorText + ":via inspector";
+        this.__proto__ = WebInspector.StylePropertiesSection.prototype;
+    }
+}
+
+WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype;
+
+WebInspector.StylePropertyTreeElement = function(styleRule, style, property, shorthand, inherited, overloaded)
+{
+    this._styleRule = styleRule;
+    this.style = style;
+    this.property = property;
+    this.shorthand = shorthand;
+    this._inherited = inherited;
+    this._overloaded = overloaded;
+
+    // Pass an empty title, the title gets made later in onattach.
+    TreeElement.call(this, "", null, shorthand);
+}
+
+WebInspector.StylePropertyTreeElement.prototype = {
+    get inherited()
+    {
+        return this._inherited;
+    },
+
+    set inherited(x)
+    {
+        if (x === this._inherited)
+            return;
+        this._inherited = x;
+        this.updateState();
+    },
+
+    get overloaded()
+    {
+        return this._overloaded;
+    },
+
+    set overloaded(x)
+    {
+        if (x === this._overloaded)
+            return;
+        this._overloaded = x;
+        this.updateState();
+    },
+
+    get disabled()
+    {
+        return this.property.disabled;
+    },
+
+    get name()
+    {
+        if (!this.disabled || !this.property.text)
+            return this.property.name;
+
+        var text = this.property.text;
+        var index = text.indexOf(":");
+        if (index < 1)
+            return this.property.name;
+
+        return text.substring(0, index).trim();
+    },
+
+    get priority()
+    {
+        if (this.disabled)
+            return ""; // rely upon raw text to render it in the value field
+        return this.property.priority;
+    },
+
+    get value()
+    {
+        if (!this.disabled || !this.property.text)
+            return this.property.value;
+
+        var match = this.property.text.match(/(.*);\s*/);
+        if (!match || !match[1])
+            return this.property.value;
+
+        var text = match[1];
+        var index = text.indexOf(":");
+        if (index < 1)
+            return this.property.value;
+
+        return text.substring(index + 1).trim();
+    },
+
+    get parsedOk()
+    {
+        return this.property.parsedOk;
+    },
+
+    onattach: function()
+    {
+        this.updateTitle();
+    },
+
+    updateTitle: function()
+    {
+        var value = this.value;
+
+        this.updateState();
+
+        var enabledCheckboxElement;
+        if (this.parsedOk) {
+            enabledCheckboxElement = document.createElement("input");
+            enabledCheckboxElement.className = "enabled-button";
+            enabledCheckboxElement.type = "checkbox";
+            enabledCheckboxElement.checked = !this.disabled;
+            enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false);
+        }
+
+        var nameElement = document.createElement("span");
+        nameElement.className = "webkit-css-property";
+        nameElement.textContent = this.name;
+        this.nameElement = nameElement;
+
+        var valueElement = document.createElement("span");
+        valueElement.className = "value";
+        this.valueElement = valueElement;
+
+        if (value) {
+            var self = this;
+
+            function processValue(regex, processor, nextProcessor, valueText)
+            {
+                var container = document.createDocumentFragment();
+
+                var items = valueText.replace(regex, "\0$1\0").split("\0");
+                for (var i = 0; i < items.length; ++i) {
+                    if ((i % 2) === 0) {
+                        if (nextProcessor)
+                            container.appendChild(nextProcessor(items[i]));
+                        else
+                            container.appendChild(document.createTextNode(items[i]));
+                    } else {
+                        var processedNode = processor(items[i]);
+                        if (processedNode)
+                            container.appendChild(processedNode);
+                    }
+                }
+
+                return container;
+            }
+
+            function linkifyURL(url)
+            {
+                var hrefUrl = url;
+                var match = hrefUrl.match(/['"]?([^'"]+)/);
+                if (match)
+                    hrefUrl = match[1];
+                var container = document.createDocumentFragment();
+                container.appendChild(document.createTextNode("url("));
+                if (self._styleRule.sourceURL)
+                    hrefUrl = WebInspector.completeURL(self._styleRule.sourceURL, hrefUrl);
+                else if (WebInspector.panels.elements.focusedDOMNode)
+                    hrefUrl = WebInspector.resourceURLForRelatedNode(WebInspector.panels.elements.focusedDOMNode, hrefUrl);
+                var hasResource = !!WebInspector.resourceForURL(hrefUrl);
+                // FIXME: WebInspector.linkifyURLAsNode() should really use baseURI.
+                container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, null, hasResource));
+                container.appendChild(document.createTextNode(")"));
+                return container;
+            }
+
+            function processColor(text)
+            {
+                try {
+                    var color = new WebInspector.Color(text);
+                } catch (e) {
+                    return document.createTextNode(text);
+                }
+
+                var swatchElement = document.createElement("span");
+                swatchElement.title = WebInspector.UIString("Click to change color format");
+                swatchElement.className = "swatch";
+                swatchElement.style.setProperty("background-color", text);
+
+                swatchElement.addEventListener("click", changeColorDisplay, false);
+                swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false);
+
+                var format;
+                if (WebInspector.settings.colorFormat === "original")
+                    format = "original";
+                else if (Preferences.showColorNicknames && color.nickname)
+                    format = "nickname";
+                else if (WebInspector.settings.colorFormat === "rgb")
+                    format = (color.simple ? "rgb" : "rgba");
+                else if (WebInspector.settings.colorFormat === "hsl")
+                    format = (color.simple ? "hsl" : "hsla");
+                else if (color.simple)
+                    format = (color.hasShortHex() ? "shorthex" : "hex");
+                else
+                    format = "rgba";
+
+                var colorValueElement = document.createElement("span");
+                colorValueElement.textContent = color.toString(format);
+
+                function nextFormat(curFormat)
+                {
+                    // The format loop is as follows:
+                    // * original
+                    // * rgb(a)
+                    // * hsl(a)
+                    // * nickname (if the color has a nickname)
+                    // * if the color is simple:
+                    //   - shorthex (if has short hex)
+                    //   - hex
+                    switch (curFormat) {
+                        case "original":
+                            return color.simple ? "rgb" : "rgba";
+
+                        case "rgb":
+                        case "rgba":
+                            return color.simple ? "hsl" : "hsla";
+
+                        case "hsl":
+                        case "hsla":
+                            if (color.nickname)
+                                return "nickname";
+                            if (color.simple)
+                                return color.hasShortHex() ? "shorthex" : "hex";
+                            else
+                                return "original";
+
+                        case "shorthex":
+                            return "hex";
+
+                        case "hex":
+                            return "original";
+
+                        case "nickname":
+                            if (color.simple)
+                                return color.hasShortHex() ? "shorthex" : "hex";
+                            else
+                                return "original";
+
+                        default:
+                            return null;
+                    }
+                }
+
+                function changeColorDisplay(event)
+                {
+                    do {
+                        format = nextFormat(format);
+                        var currentValue = color.toString(format || "");
+                    } while (format && currentValue === color.value && format !== "original");
+
+                    if (format)
+                        colorValueElement.textContent = currentValue;
+                }
+
+                var container = document.createDocumentFragment();
+                container.appendChild(swatchElement);
+                container.appendChild(colorValueElement);
+                return container;
+            }
+
+            var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g;
+            var colorProcessor = processValue.bind(window, colorRegex, processColor, null);
+
+            valueElement.appendChild(processValue(/url\(\s*([^)\s]+)\s*\)/g, linkifyURL, colorProcessor, value));
+        }
+
+        this.listItemElement.removeChildren();
+        nameElement.normalize();
+        valueElement.normalize();
+
+        if (!this.treeOutline)
+            return;
+
+        // Append the checkbox for root elements of an editable section.
+        if (enabledCheckboxElement && this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
+            this.listItemElement.appendChild(enabledCheckboxElement);
+        this.listItemElement.appendChild(nameElement);
+        this.listItemElement.appendChild(document.createTextNode(": "));
+        this.listItemElement.appendChild(valueElement);
+        this.listItemElement.appendChild(document.createTextNode(";"));
+
+        if (!this.parsedOk) {
+            // Avoid having longhands under an invalid shorthand.
+            this.hasChildren = false;
+            this.listItemElement.addStyleClass("not-parsed-ok");
+        }
+        if (this.property.inactive)
+            this.listItemElement.addStyleClass("inactive");
+
+        this.tooltip = this.property.propertyText;
+    },
+
+    updateAll: function(updateAllRules)
+    {
+        if (!this.treeOutline)
+            return;
+        if (updateAllRules && this.treeOutline.section && this.treeOutline.section.pane)
+            this.treeOutline.section.pane.update(null, this.treeOutline.section);
+        else if (this.treeOutline.section)
+            this.treeOutline.section.update(true);
+        else
+            this.updateTitle(); // FIXME: this will not show new properties. But we don't hit this case yet.
+    },
+
+    toggleEnabled: function(event)
+    {
+        var disabled = !event.target.checked;
+
+        function callback(newStyle)
+        {
+            if (!newStyle)
+                return;
+
+            this.style = newStyle;
+            this._styleRule.style = newStyle;
+
+            if (this.treeOutline.section && this.treeOutline.section.pane)
+                this.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
+
+            this.updateAll(true);
+        }
+
+        this.property.setDisabled(disabled, callback.bind(this));
+    },
+
+    updateState: function()
+    {
+        if (!this.listItemElement)
+            return;
+
+        if (this.style.isPropertyImplicit(this.name) || this.value === "initial")
+            this.listItemElement.addStyleClass("implicit");
+        else
+            this.listItemElement.removeStyleClass("implicit");
+
+        this.selectable = !this.inherited;
+        if (this.inherited)
+            this.listItemElement.addStyleClass("inherited");
+        else
+            this.listItemElement.removeStyleClass("inherited");
+
+        if (this.overloaded)
+            this.listItemElement.addStyleClass("overloaded");
+        else
+            this.listItemElement.removeStyleClass("overloaded");
+
+        if (this.disabled)
+            this.listItemElement.addStyleClass("disabled");
+        else
+            this.listItemElement.removeStyleClass("disabled");
+    },
+
+    onpopulate: function()
+    {
+        // Only populate once and if this property is a shorthand.
+        if (this.children.length || !this.shorthand)
+            return;
+
+        var longhandProperties = this.style.getLonghandProperties(this.name);
+        for (var i = 0; i < longhandProperties.length; ++i) {
+            var name = longhandProperties[i].name;
+
+
+            if (this.treeOutline.section) {
+                var inherited = this.treeOutline.section.isPropertyInherited(name);
+                var overloaded = this.treeOutline.section.isPropertyOverloaded(name);
+            }
+
+            var liveProperty = this.style.getLiveProperty(name);
+            var item = new WebInspector.StylePropertyTreeElement(this._styleRule, this.style, liveProperty, false, inherited, overloaded);
+            this.appendChild(item);
+        }
+    },
+
+    ondblclick: function(event)
+    {
+        this.startEditing(event.target);
+        event.stopPropagation();
+    },
+
+    restoreNameElement: function()
+    {
+        // Restore <span class="webkit-css-property"> if it doesn't yet exist or was accidentally deleted.
+        if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property"))
+            return;
+
+        this.nameElement = document.createElement("span");
+        this.nameElement.className = "webkit-css-property";
+        this.nameElement.textContent = "";
+        this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild);
+    },
+
+    startEditing: function(selectElement)
+    {
+        // FIXME: we don't allow editing of longhand properties under a shorthand right now.
+        if (this.parent.shorthand)
+            return;
+
+        if (this.treeOutline.section && !this.treeOutline.section.editable)
+            return;
+
+        if (!selectElement)
+            selectElement = this.nameElement; // No arguments passed in - edit the name element by default.
+        else
+            selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value");
+
+        var isEditingName = selectElement === this.nameElement;
+        if (!isEditingName && selectElement !== this.valueElement) {
+            // Double-click in the LI - start editing value.
+            isEditingName = false;
+            selectElement = this.valueElement;
+        }
+
+        if (WebInspector.isBeingEdited(selectElement))
+            return;
+
+        var context = {
+            expanded: this.expanded,
+            hasChildren: this.hasChildren,
+            keyDownListener: isEditingName ? null : this.editingValueKeyDown.bind(this),
+            isEditingName: isEditingName,
+        };
+
+        // Lie about our children to prevent expanding on double click and to collapse shorthands.
+        this.hasChildren = false;
+
+        if (!isEditingName)
+            selectElement.addEventListener("keydown", context.keyDownListener, false);
+        if (selectElement.parentElement)
+            selectElement.parentElement.addStyleClass("child-editing");
+        selectElement.textContent = selectElement.textContent; // remove color swatch and the like
+
+        function shouldCommitValueSemicolon(text, cursorPosition)
+        {
+            // FIXME: should this account for semicolons inside comments?
+            var openQuote = "";
+            for (var i = 0; i < cursorPosition; ++i) {
+                var ch = text[i];
+                if (ch === "\\" && openQuote !== "")
+                    ++i; // skip next character inside string
+                else if (!openQuote && (ch === "\"" || ch === "'"))
+                    openQuote = ch;
+                else if (openQuote === ch)
+                    openQuote = "";
+            }
+            return !openQuote;
+        }
+
+        function nameValueFinishHandler(context, isEditingName, event)
+        {
+            // FIXME: the ":"/";" detection does not work for non-US layouts due to the event being keydown rather than keypress.
+            var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) &&
+                (isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset)));
+            if (isEnterKey(event) || isFieldInputTerminated) {
+                // Enter or colon (for name)/semicolon outside of string (for value).
+                event.preventDefault();
+                return "move-forward";
+            } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
+                return "cancel";
+            else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) {
+                // For a new property, when Backspace is pressed at the beginning of new property value, move back to the property name.
+                var selection = window.getSelection();
+                if (selection.isCollapsed && !selection.focusOffset) {
+                    event.preventDefault();
+                    return "move-backward";
+                }
+            } else if (event.keyIdentifier === "U+0009") // Tab key.
+                return "move-" + (event.shiftKey ? "backward" : "forward");
+        }
+
+        function pasteHandler(context, event)
+        {
+            var data = event.clipboardData.getData("Text");
+            if (!data)
+                return;
+            var colonIdx = data.indexOf(":");
+            if (colonIdx < 0)
+                return;
+            var name = data.substring(0, colonIdx).trim();
+            var value = data.substring(colonIdx + 1).trim();
+
+            event.preventDefault();
+
+            if (!("originalName" in context)) {
+                context.originalName = this.nameElement.textContent;
+                context.originalValue = this.valueElement.textContent;
+            }
+            this.nameElement.textContent = name;
+            this.valueElement.textContent = value;
+            this.nameElement.normalize();
+            this.valueElement.normalize();
+
+            return "move-forward";
+        }
+
+        WebInspector.startEditing(selectElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this),
+            customFinishHandler: nameValueFinishHandler.bind(this, context, isEditingName),
+            pasteHandler: isEditingName ? pasteHandler.bind(this, context) : null
+        });
+
+        this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(selectElement, isEditingName ? WebInspector.cssNameCompletions : WebInspector.CSSKeywordCompletions.forProperty(this.nameElement.textContent));
+        window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
+    },
+
+    editingValueKeyDown: function(event)
+    {
+        if (event.handled)
+            return;
+        var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
+        var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown");
+        if (!arrowKeyPressed && !pageKeyPressed)
+            return;
+
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        if (selectionRange.commonAncestorContainer !== this.valueElement && !selectionRange.commonAncestorContainer.isDescendant(this.valueElement))
+            return;
+
+        var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this.valueElement);
+        var wordString = wordRange.toString();
+        var replacementString = wordString;
+
+        var matches = /(.*?)(-?\d+(?:\.\d+)?)(.*)/.exec(wordString);
+        if (matches && matches.length) {
+            var prefix = matches[1];
+            var number = parseFloat(matches[2]);
+            var suffix = matches[3];
+
+            // If the number is near zero or the number is one and the direction will take it near zero.
+            var numberNearZero = (number < 1 && number > -1);
+            if (number === 1 && event.keyIdentifier === "Down")
+                numberNearZero = true;
+            else if (number === -1 && event.keyIdentifier === "Up")
+                numberNearZero = true;
+
+            if (numberNearZero && event.altKey && arrowKeyPressed) {
+                if (event.keyIdentifier === "Down")
+                    number = Math.ceil(number - 1);
+                else
+                    number = Math.floor(number + 1);
+            } else {
+                // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down.
+                // Also jump by 10 for page up and down, or by 100 if shift is held with a page key.
+                var changeAmount = 1;
+                if (event.shiftKey && pageKeyPressed)
+                    changeAmount = 100;
+                else if (event.shiftKey || pageKeyPressed)
+                    changeAmount = 10;
+                else if (event.altKey || numberNearZero)
+                    changeAmount = 0.1;
+
+                if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown")
+                    changeAmount *= -1;
+
+                // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns.
+                // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1.
+                number = Number((number + changeAmount).toFixed(6));
+            }
+
+            replacementString = prefix + number + suffix;
+
+            var replacementTextNode = document.createTextNode(replacementString);
+
+            wordRange.deleteContents();
+            wordRange.insertNode(replacementTextNode);
+
+            var finalSelectionRange = document.createRange();
+            finalSelectionRange.setStart(replacementTextNode, 0);
+            finalSelectionRange.setEnd(replacementTextNode, replacementString.length);
+
+            selection.removeAllRanges();
+            selection.addRange(finalSelectionRange);
+
+            event.handled = true;
+            event.preventDefault();
+
+            if (!("originalPropertyText" in this)) {
+                // Remember the rule's original CSS text on [Page](Up|Down), so it can be restored
+                // if the editing is canceled.
+                this.originalPropertyText = this.property.propertyText;
+            }
+
+            // Synthesize property text disregarding any comments, custom whitespace etc.
+            this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent);
+        }
+    },
+
+    editingEnded: function(context)
+    {
+        this.hasChildren = context.hasChildren;
+        if (context.expanded)
+            this.expand();
+        var editedElement = context.isEditingName ? this.nameElement : this.valueElement;
+        if (!context.isEditingName)
+            editedElement.removeEventListener("keydown", context.keyDownListener, false);
+        if (editedElement.parentElement)
+            editedElement.parentElement.removeStyleClass("child-editing");
+
+        delete this.originalPropertyText;
+    },
+
+    editingCancelled: function(element, context)
+    {
+        this._removePrompt();
+        if ("originalPropertyText" in this)
+            this.applyStyleText(this.originalPropertyText, true);
+        else {
+            if (this._newProperty)
+                this.treeOutline.removeChild(this);
+            else
+                this.updateTitle();
+        }
+
+        // This should happen last, as it clears the info necessary to restore the property value after [Page]Up/Down changes.
+        this.editingEnded(context);
+    },
+
+    editingCommitted: function(element, userInput, previousContent, context, moveDirection)
+    {
+        this._removePrompt();
+        this.editingEnded(context);
+        var isEditingName = context.isEditingName;
+
+        // Determine where to move to before making changes
+        var createNewProperty, moveToPropertyName, moveToSelector;
+        var moveTo = this;
+        var moveToOther = (isEditingName ^ (moveDirection === "forward"));
+        var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName);
+        if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) {
+            do {
+                moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling);
+            } while(moveTo && !moveTo.selectable);
+
+           if (moveTo)
+                moveToPropertyName = moveTo.name;
+            else if (moveDirection === "forward" && (!this._newProperty || userInput))
+                createNewProperty = true;
+            else if (moveDirection === "backward" && this.treeOutline.section.rule)
+                moveToSelector = true;
+        }
+
+        // Make the Changes and trigger the moveToNextCallback after updating.
+        var blankInput = /^\s*$/.test(userInput);
+        var isDataPasted = "originalName" in context;
+        var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue);
+        var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput));
+        if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) {
+            this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section);
+            var propertyText;
+            if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent)))
+                propertyText = "";
+            else {
+                if (isEditingName)
+                    propertyText = userInput + ": " + this.valueElement.textContent;
+                else
+                    propertyText = this.nameElement.textContent + ": " + userInput;
+            }
+            this.applyStyleText(propertyText, true);
+        } else {
+            if (!isDataPasted && !this._newProperty)
+                this.updateTitle();
+            moveToNextCallback(this._newProperty, false, this.treeOutline.section);
+        }
+
+        var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;
+
+        // The Callback to start editing the next/previous property/selector.
+        function moveToNextCallback(alreadyNew, valueChanged, section)
+        {
+            if (!moveDirection)
+                return;
+
+            // User just tabbed through without changes.
+            if (moveTo && moveTo.parent) {
+                moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement);
+                return;
+            }
+
+            // User has made a change then tabbed, wiping all the original treeElements.
+            // Recalculate the new treeElement for the same property we were going to edit next.
+            if (moveTo && !moveTo.parent) {
+                var propertyElements = section.propertiesTreeOutline.children;
+                if (moveDirection === "forward" && blankInput && !isEditingName)
+                    --moveToIndex;
+                if (moveToIndex >= propertyElements.length && !this._newProperty)
+                    createNewProperty = true;
+                else {
+                    var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null;
+                    if (treeElement) {
+                        treeElement.startEditing(!isEditingName ? treeElement.nameElement : treeElement.valueElement);
+                        return;
+                    } else if (!alreadyNew)
+                        moveToSelector = true;
+                }
+            }
+
+            // Create a new attribute in this section (or move to next editable selector if possible).
+            if (createNewProperty) {
+                if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward")))
+                    return;
+
+                section.addNewBlankProperty().startEditing();
+                return;
+            }
+
+            if (abandonNewProperty) {
+                var sectionToEdit = moveDirection === "backward" ? section : section.nextEditableSibling();
+                if (sectionToEdit && sectionToEdit.rule)
+                    sectionToEdit.startEditingSelector();
+                return;
+            }
+
+            if (moveToSelector)
+                section.startEditingSelector();
+        }
+    },
+
+    _removePrompt: function()
+    {
+        // BUG 53242. This cannot go into editingEnded(), as it should always happen first for any editing outcome.
+        if (this._prompt) {
+            this._prompt.removeFromElement();
+            delete this._prompt;
+        }
+    },
+
+    _hasBeenAppliedToPageViaUpDown: function()
+    {
+        // New properties applied via up/down have an originalPropertyText and will be deleted later
+        // on, if cancelled, when the empty string gets applied as their style text.
+        return ("originalPropertyText" in this);
+    },
+
+    applyStyleText: function(styleText, updateInterface)
+    {
+        var section = this.treeOutline.section;
+        var elementsPanel = WebInspector.panels.elements;
+        styleText = styleText.replace(/\s/g, " ").trim(); // Replace &nbsp; with whitespace.
+        var styleTextLength = styleText.length;
+        if (!styleTextLength && updateInterface && this._newProperty && !this._hasBeenAppliedToPageViaUpDown()) {
+            // The user deleted everything and never applied a new property value via Up/Down scrolling, so remove the tree element and update.
+            this.parent.removeChild(this);
+            section.afterUpdate();
+            return;
+        }
+
+        function callback(newStyle)
+        {
+            if (!newStyle) {
+                // The user typed something, but it didn't parse. Just abort and restore
+                // the original title for this property.  If this was a new attribute and
+                // we couldn't parse, then just remove it.
+                if (this._newProperty) {
+                    this.parent.removeChild(this);
+                    return;
+                }
+                if (updateInterface)
+                    this.updateTitle();
+                return;
+            }
+
+            this.style = newStyle;
+            this.property = newStyle.propertyAt(this.property.index);
+            this._styleRule.style = this.style;
+
+            if (section && section.pane)
+                section.pane.dispatchEventToListeners("style edited");
+
+            if (updateInterface)
+                this.updateAll(true);
+        }
+
+        // Append a ";" if the new text does not end in ";".
+        // FIXME: this does not handle trailing comments.
+        if (styleText.length && !/;\s*$/.test(styleText))
+            styleText += ";";
+        this.property.setText(styleText, updateInterface, callback.bind(this));
+    }
+}
+
+WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+WebInspector.StylesSidebarPane.CSSPropertyPrompt = function(element, cssCompletions)
+{
+    WebInspector.TextPrompt.call(this, element, this._buildPropertyCompletions.bind(this), WebInspector.StylesSidebarPane.StyleValueDelimiters, true);
+    this._cssCompletions = cssCompletions;
+}
+
+WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = {
+    upKeyPressed: function(event)
+    {
+        this._handleNameOrValueUpDown(event);
+    },
+
+    downKeyPressed: function(event)
+    {
+        this._handleNameOrValueUpDown(event);
+    },
+
+    tabKeyPressed: function(event)
+    {
+        this.acceptAutoComplete();
+    },
+
+    _handleNameOrValueUpDown: function(event)
+    {
+        var reverse = event.keyIdentifier === "Up";
+        if (this.autoCompleteElement)
+            this.complete(false, reverse); // Accept the current suggestion, if any.
+        else {
+            // Select the word suffix to affect it when computing the subsequent suggestion.
+            this._selectCurrentWordSuffix();
+        }
+
+        this.complete(false, reverse); // Actually increment/decrement the suggestion.
+        event.handled = true;
+    },
+
+    _selectCurrentWordSuffix: function()
+    {
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        if (!selectionRange.commonAncestorContainer.isDescendant(this.element))
+            return;
+        var wordSuffixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this.element, "forward");
+        if (!wordSuffixRange.toString())
+            return;
+        selection.removeAllRanges();
+        selection.addRange(wordSuffixRange);
+    },
+
+    _buildPropertyCompletions: function(wordRange, bestMatchOnly, completionsReadyCallback)
+    {
+        var prefix = wordRange.toString().toLowerCase();
+        var results;
+        if (bestMatchOnly) {
+            results = [];
+            var firstMatch = this._cssCompletions.firstStartsWith(prefix);
+            if (firstMatch)
+                results.push(firstMatch);
+            return completionsReadyCallback(results);
+        }
+
+        results = this._cssCompletions.startsWith(prefix);
+        if (results)
+            completionsReadyCallback(results);
+    }
+}
+
+WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js
new file mode 100644
index 0000000..4bd5c65
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SummaryBar = function(categories)
+{
+    this.categories = categories;
+
+    this.element = document.createElement("div");
+    this.element.className = "summary-bar";
+
+    this.graphElement = document.createElement("canvas");
+    this.graphElement.setAttribute("width", "450");
+    this.graphElement.setAttribute("height", "38");
+    this.graphElement.className = "summary-graph";
+    this.element.appendChild(this.graphElement);
+
+    this.legendElement = document.createElement("div");
+    this.legendElement.className = "summary-graph-legend";
+    this.element.appendChild(this.legendElement);
+}
+
+WebInspector.SummaryBar.prototype = {
+
+    get calculator() {
+        return this._calculator;
+    },
+
+    set calculator(x) {
+        this._calculator = x;
+    },
+
+    reset: function()
+    {
+        this.legendElement.removeChildren();
+        this._drawSummaryGraph();
+    },
+
+    update: function(data)
+    {
+        var graphInfo = this.calculator.computeSummaryValues(data);
+
+        var fillSegments = [];
+
+        this.legendElement.removeChildren();
+
+        for (var category in this.categories) {
+            var size = graphInfo.categoryValues[category];
+            if (!size)
+                continue;
+
+            var colorString = this.categories[category].color;
+
+            var fillSegment = {color: colorString, value: size};
+            fillSegments.push(fillSegment);
+
+            var legendLabel = this._makeLegendElement(this.categories[category].title, this.calculator.formatValue(size), colorString);
+            this.legendElement.appendChild(legendLabel);
+        }
+
+        if (graphInfo.total) {
+            var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
+            totalLegendLabel.addStyleClass("total");
+            this.legendElement.appendChild(totalLegendLabel);
+        }
+
+        this._drawSummaryGraph(fillSegments);
+    },
+
+    _drawSwatch: function(canvas, color)
+    {
+        var ctx = canvas.getContext("2d");
+
+        function drawSwatchSquare() {
+            ctx.fillStyle = color;
+            ctx.fillRect(0, 0, 13, 13);
+
+            var gradient = ctx.createLinearGradient(0, 0, 13, 13);
+            gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
+            gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+            ctx.fillStyle = gradient;
+            ctx.fillRect(0, 0, 13, 13);
+
+            gradient = ctx.createLinearGradient(13, 13, 0, 0);
+            gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
+            gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
+
+            ctx.fillStyle = gradient;
+            ctx.fillRect(0, 0, 13, 13);
+
+            ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
+            ctx.strokeRect(0.5, 0.5, 12, 12);
+        }
+
+        ctx.clearRect(0, 0, 13, 24);
+
+        drawSwatchSquare();
+
+        ctx.save();
+
+        ctx.translate(0, 25);
+        ctx.scale(1, -1);
+
+        drawSwatchSquare();
+
+        ctx.restore();
+
+        this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
+    },
+
+    _drawSummaryGraph: function(segments)
+    {
+        if (!segments || !segments.length) {
+            segments = [{color: "white", value: 1}];
+            this._showingEmptySummaryGraph = true;
+        } else
+            delete this._showingEmptySummaryGraph;
+
+        // Calculate the total of all segments.
+        var total = 0;
+        for (var i = 0; i < segments.length; ++i)
+            total += segments[i].value;
+
+        // Calculate the percentage of each segment, rounded to the nearest percent.
+        var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
+
+        // Calculate the total percentage.
+        var percentTotal = 0;
+        for (var i = 0; i < percents.length; ++i)
+            percentTotal += percents[i];
+
+        // Make sure our percentage total is not greater-than 100, it can be greater
+        // if we rounded up for a few segments.
+        while (percentTotal > 100) {
+            for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
+                if (percents[i] > 1) {
+                    --percents[i];
+                    --percentTotal;
+                }
+            }
+        }
+
+        // Make sure our percentage total is not less-than 100, it can be less
+        // if we rounded down for a few segments.
+        while (percentTotal < 100) {
+            for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
+                ++percents[i];
+                ++percentTotal;
+            }
+        }
+
+        var ctx = this.graphElement.getContext("2d");
+
+        var x = 0;
+        var y = 0;
+        var w = 450;
+        var h = 19;
+        var r = (h / 2);
+
+        function drawPillShadow()
+        {
+            // This draws a line with a shadow that is offset away from the line. The line is stroked
+            // twice with different X shadow offsets to give more feathered edges. Later we erase the
+            // line with destination-out 100% transparent black, leaving only the shadow. This only
+            // works if nothing has been drawn into the canvas yet.
+
+            ctx.beginPath();
+            ctx.moveTo(x + 4, y + h - 3 - 0.5);
+            ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
+            ctx.closePath();
+
+            ctx.save();
+
+            ctx.shadowBlur = 2;
+            ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
+            ctx.shadowOffsetX = 3;
+            ctx.shadowOffsetY = 5;
+
+            ctx.strokeStyle = "white";
+            ctx.lineWidth = 1;
+
+            ctx.stroke();
+
+            ctx.shadowOffsetX = -3;
+
+            ctx.stroke();
+
+            ctx.restore();
+
+            ctx.save();
+
+            ctx.globalCompositeOperation = "destination-out";
+            ctx.strokeStyle = "rgba(0, 0, 0, 1)";
+            ctx.lineWidth = 1;
+
+            ctx.stroke();
+
+            ctx.restore();
+        }
+
+        function drawPill()
+        {
+            // Make a rounded rect path.
+            ctx.beginPath();
+            ctx.moveTo(x, y + r);
+            ctx.lineTo(x, y + h - r);
+            ctx.arc(x + r, y + h - r, r, Math.PI, Math.PI / 2, true);
+            ctx.lineTo(x + w - r, y + h);
+            ctx.arc(x + w - r, y + h - r, r, Math.PI / 2, 0, true);
+            ctx.lineTo(x + w, y + r);
+            ctx.arc(x + w - r, y + r, r, 0, 3 * Math.PI / 2, true);
+            ctx.lineTo(x + r, y);
+            ctx.arc(x + r, y + r, r, Math.PI / 2, Math.PI, true);
+            ctx.closePath();
+
+            // Clip to the rounded rect path.
+            ctx.save();
+            ctx.clip();
+
+            // Fill the segments with the associated color.
+            var previousSegmentsWidth = 0;
+            for (var i = 0; i < segments.length; ++i) {
+                var segmentWidth = Math.round(w * percents[i] / 100);
+                ctx.fillStyle = segments[i].color;
+                ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
+                previousSegmentsWidth += segmentWidth;
+            }
+
+            // Draw the segment divider lines.
+            ctx.lineWidth = 1;
+            for (var i = 1; i < 20; ++i) {
+                ctx.beginPath();
+                ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
+                ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
+                ctx.closePath();
+
+                ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
+                ctx.stroke();
+
+                ctx.beginPath();
+                ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
+                ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
+                ctx.closePath();
+
+                ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
+                ctx.stroke();
+            }
+
+            // Draw the pill shading.
+            var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
+            lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
+            lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
+            lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+            var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
+            darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
+            darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
+            darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
+
+            ctx.fillStyle = darkGradient;
+            ctx.fillRect(x, y, w, h);
+
+            ctx.fillStyle = lightGradient;
+            ctx.fillRect(x, y, w, h);
+
+            ctx.restore();
+        }
+
+        ctx.clearRect(x, y, w, (h * 2));
+
+        drawPillShadow();
+        drawPill();
+
+        ctx.save();
+
+        ctx.translate(0, (h * 2) + 1);
+        ctx.scale(1, -1);
+
+        drawPill();
+
+        ctx.restore();
+
+        this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
+    },
+
+    _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
+    {
+        ctx.save();
+
+        var gradient = ctx.createLinearGradient(x, y, x, y + h);
+        gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
+        gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
+        gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
+
+        ctx.globalCompositeOperation = "destination-out";
+
+        ctx.fillStyle = gradient;
+        ctx.fillRect(x, y, w, h);
+
+        ctx.restore();
+    },
+
+    _makeLegendElement: function(label, value, color)
+    {
+        var legendElement = document.createElement("label");
+        legendElement.className = "summary-graph-legend-item";
+
+        if (color) {
+            var swatch = document.createElement("canvas");
+            swatch.className = "summary-graph-legend-swatch";
+            swatch.setAttribute("width", "13");
+            swatch.setAttribute("height", "24");
+
+            legendElement.appendChild(swatch);
+
+            this._drawSwatch(swatch, color);
+        }
+
+        var labelElement = document.createElement("div");
+        labelElement.className = "summary-graph-legend-label";
+        legendElement.appendChild(labelElement);
+
+        var headerElement = document.createElement("div");
+        headerElement.className = "summary-graph-legend-header";
+        headerElement.textContent = label;
+        labelElement.appendChild(headerElement);
+
+        var valueElement = document.createElement("div");
+        valueElement.className = "summary-graph-legend-value";
+        valueElement.textContent = value;
+        labelElement.appendChild(valueElement);
+
+        return legendElement;
+    }
+}
+
+WebInspector.SummaryBar.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js
new file mode 100644
index 0000000..84ab702
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TabbedPane = function(element)
+{
+    this.element = element || document.createElement("div");
+    this.element.addStyleClass("tabbed-pane");
+    this._tabsElement = this.element.createChild("div", "tabbed-pane-header");
+    this._contentElement = this.element.createChild("div", "tabbed-pane-content");
+    this._tabs = {};
+}
+
+WebInspector.TabbedPane.prototype = {
+    appendTab: function(id, tabTitle, view)
+    {
+        var tabElement = document.createElement("li");
+        tabElement.textContent = tabTitle;
+        tabElement.addEventListener("click", this.selectTab.bind(this, id, true), false);
+
+        this._tabsElement.appendChild(tabElement);
+        this._contentElement.appendChild(view.element);
+
+        this._tabs[id] = { tabElement: tabElement, view: view }
+    },
+
+    selectTab: function(id, userGesture)
+    {
+        if (!(id in this._tabs))
+            return false;
+
+        if (this._currentTab) {
+            this._hideTab(this._currentTab)
+            delete this._currentTab;
+        }
+
+        var tab = this._tabs[id];
+        this._showTab(tab);
+        this._currentTab = tab;
+        if (userGesture) {
+            var event = {tabId: id};
+            this.dispatchEventToListeners("tab-selected", event);
+        }
+        return true;
+    },
+
+    _showTab: function(tab)
+    {
+        tab.tabElement.addStyleClass("selected");
+        tab.view.show(this._contentElement);
+    },
+
+    _hideTab: function(tab)
+    {
+        tab.tabElement.removeStyleClass("selected");
+        tab.view.visible = false;
+    }
+}
+
+WebInspector.TabbedPane.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js
new file mode 100644
index 0000000..3bfe28c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TestController = function(callId)
+{
+    this._callId = callId;
+    this._waitUntilDone = false;
+    this.results = [];
+}
+
+WebInspector.TestController.prototype = {
+    waitUntilDone: function()
+    {
+        this._waitUntilDone = true;
+    },
+
+    notifyDone: function(result)
+    {
+        if (typeof result === "undefined" && this.results.length)
+            result = this.results;
+        var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result);
+        InspectorBackend.didEvaluateForTestInFrontend(this._callId, message);
+    },
+
+    runAfterPendingDispatches: function(callback)
+    {
+        if (WebInspector.pendingDispatches === 0) {
+            callback();
+            return;
+        }
+        setTimeout(this.runAfterPendingDispatches.bind(this), 0, callback);
+    }
+}
+
+WebInspector.evaluateForTestInFrontend = function(callId, script)
+{
+    var controller = new WebInspector.TestController(callId);
+    function invokeMethod()
+    {
+        try {
+            var result;
+            if (window[script] && typeof window[script] === "function")
+                result = window[script].call(WebInspector, controller);
+            else
+                result = window.eval(script);
+
+            if (!controller._waitUntilDone)
+                controller.notifyDone(result);
+        } catch (e) {
+            controller.notifyDone(e.toString());
+        }
+    }
+    controller.runAfterPendingDispatches(invokeMethod);
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js
new file mode 100644
index 0000000..4ac831e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
+{
+    this._textModel = textModel;
+    this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html");
+    this._damageCallback = damageCallback;
+    this.reset();
+}
+
+WebInspector.TextEditorHighlighter.prototype = {
+    set mimeType(mimeType)
+    {
+        var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
+        if (tokenizer) {
+            this._tokenizer = tokenizer;
+            this._tokenizerCondition = this._tokenizer.initialCondition;
+        }
+    },
+
+    reset: function()
+    {
+        this._lastHighlightedLine = 0;
+        this._lastHighlightedColumn = 0;
+        this._tokenizerCondition = this._tokenizer.initialCondition;
+    },
+
+    highlight: function(endLine)
+    {
+        // First check if we have work to do.
+        if (endLine <= this._lastHighlightedLine)
+            return;
+
+        this._requestedEndLine = endLine;
+
+        if (this._highlightTimer) {
+            // There is a timer scheduled, it will catch the new job based on the new endLine set.
+            return;
+        }
+
+        // Do small highlight synchronously. This will provide instant highlight on PageUp / PageDown, gentle scrolling.
+        this._highlightInChunks(endLine);
+
+        // Schedule tail highlight if necessary.
+        if (this._lastHighlightedLine < endLine)
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
+    },
+
+    _highlightInChunks: function(endLine)
+    {
+        delete this._highlightTimer;
+
+        // First we always check if we have work to do. Could be that user scrolled back and we can quit.
+        if (this._requestedEndLine <= this._lastHighlightedLine)
+            return;
+
+        if (this._requestedEndLine !== endLine) {
+            // User keeps updating the job in between of our timer ticks. Just reschedule self, don't eat CPU (they must be scrolling).
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 100);
+            return;
+        }
+
+        this._highlightLines(this._requestedEndLine);
+
+        // Schedule tail highlight if necessary.
+        if (this._lastHighlightedLine < this._requestedEndLine)
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 10);
+    },
+
+    _highlightLines: function(endLine)
+    {
+        // Tokenizer is stateless and reused accross viewers, restore its condition before highlight and save it after.
+        this._tokenizer.condition = this._tokenizerCondition;
+        var tokensCount = 0;
+        for (var lineNumber = this._lastHighlightedLine; lineNumber < endLine; ++lineNumber) {
+            var line = this._textModel.line(lineNumber);
+            this._tokenizer.line = line;
+            var attributes = this._textModel.getAttribute(lineNumber, "highlight") || {};
+
+            // Highlight line.
+            do {
+                var newColumn = this._tokenizer.nextToken(this._lastHighlightedColumn);
+                var tokenType = this._tokenizer.tokenType;
+                if (tokenType)
+                    attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType, subTokenizer: this._tokenizer.subTokenizer };
+                this._lastHighlightedColumn = newColumn;
+                if (++tokensCount > 1000)
+                    break;
+            } while (this._lastHighlightedColumn < line.length)
+
+            this._textModel.setAttribute(lineNumber, "highlight", attributes);
+            if (this._lastHighlightedColumn < line.length) {
+                // Too much work for single chunk - exit.
+                break;
+            } else
+                this._lastHighlightedColumn = 0;
+        }
+
+        this._damageCallback(this._lastHighlightedLine, lineNumber);
+        this._tokenizerCondition = this._tokenizer.condition;
+        this._lastHighlightedLine = lineNumber;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js
new file mode 100644
index 0000000..f23ce76
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn)
+{
+    this.startLine = startLine;
+    this.startColumn = startColumn;
+    this.endLine = endLine;
+    this.endColumn = endColumn;
+}
+
+WebInspector.TextRange.prototype = {
+    isEmpty: function()
+    {
+        return this.startLine === this.endLine && this.startColumn === this.endColumn;
+    },
+
+    get linesCount()
+    {
+        return this.endLine - this.startLine;
+    },
+
+    clone: function()
+    {
+        return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); 
+    }
+}
+
+WebInspector.TextEditorModel = function()
+{
+    this._lines = [""];
+    this._attributes = [];
+    this._undoStack = [];
+    this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/;
+}
+
+WebInspector.TextEditorModel.prototype = {
+    set changeListener(changeListener)
+    {
+        this._changeListener = changeListener;
+    },
+
+    get linesCount()
+    {
+        return this._lines.length;
+    },
+
+    line: function(lineNumber)
+    {
+        if (lineNumber >= this._lines.length)
+            throw "Out of bounds:" + lineNumber;
+        return this._lines[lineNumber];
+    },
+
+    lineLength: function(lineNumber)
+    {
+        return this._lines[lineNumber].length;
+    },
+
+    setText: function(range, text)
+    {
+        if (!range)
+            range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);
+        var command = this._pushUndoableCommand(range, text);
+        var newRange = this._innerSetText(range, text);
+        command.range = newRange.clone();
+
+        if (this._changeListener)
+            this._changeListener(range, newRange, command.text, text);
+        return newRange;
+    },
+
+    set replaceTabsWithSpaces(replaceTabsWithSpaces)
+    {
+        this._replaceTabsWithSpaces = replaceTabsWithSpaces;
+    },
+
+    _innerSetText: function(range, text)
+    {
+        this._eraseRange(range);
+        if (text === "")
+            return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn);
+
+        var newLines = text.split("\n");
+        this._replaceTabsIfNeeded(newLines);
+
+        var prefix = this._lines[range.startLine].substring(0, range.startColumn);
+        var prefixArguments = this._arguments
+        var suffix = this._lines[range.startLine].substring(range.startColumn);
+
+        var postCaret = prefix.length;
+        // Insert text.
+        if (newLines.length === 1) {
+            this._setLine(range.startLine, prefix + newLines[0] + suffix);
+            postCaret += newLines[0].length;
+        } else {
+            this._setLine(range.startLine, prefix + newLines[0]);
+            for (var i = 1; i < newLines.length; ++i)
+                this._insertLine(range.startLine + i, newLines[i]);
+            this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix);
+            postCaret = newLines[newLines.length - 1].length;
+        }
+        return new WebInspector.TextRange(range.startLine, range.startColumn,
+                                          range.startLine + newLines.length - 1, postCaret);
+    },
+
+    _replaceTabsIfNeeded: function(lines)
+    {
+        if (!this._replaceTabsWithSpaces)
+            return;
+        var spaces = [ "    ", "   ", "  ", " "];
+        for (var i = 0; i < lines.length; ++i) {
+            var line = lines[i];
+            var index = line.indexOf("\t");
+            while (index !== -1) {
+                line = line.substring(0, index) + spaces[index % 4] + line.substring(index + 1);
+                index = line.indexOf("\t", index + 1);
+            }
+            lines[i] = line;
+        }
+    },
+
+    _eraseRange: function(range)
+    {
+        if (range.isEmpty())
+            return;
+
+        var prefix = this._lines[range.startLine].substring(0, range.startColumn);
+        var suffix = this._lines[range.endLine].substring(range.endColumn);
+
+        if (range.endLine > range.startLine)
+            this._removeLines(range.startLine + 1, range.endLine - range.startLine);
+        this._setLine(range.startLine, prefix + suffix);
+    },
+
+    _setLine: function(lineNumber, text)
+    {
+        this._lines[lineNumber] = text;
+    },
+
+    _removeLines: function(fromLine, count)
+    {
+        this._lines.splice(fromLine, count);
+        this._attributes.splice(fromLine, count);
+    },
+
+    _insertLine: function(lineNumber, text)
+    {
+        this._lines.splice(lineNumber, 0, text);
+        this._attributes.splice(lineNumber, 0, {});
+    },
+
+    wordRange: function(lineNumber, column)
+    {
+        return new WebInspector.TextRange(lineNumber, this.wordStart(lineNumber, column, true), lineNumber, this.wordEnd(lineNumber, column, true));
+    },
+
+    wordStart: function(lineNumber, column, gapless)
+    {
+        var line = this._lines[lineNumber];
+        var prefix = line.substring(0, column).split("").reverse().join("");
+        var prefixMatch = this._noPunctuationRegex.exec(prefix);
+        return prefixMatch && (!gapless || prefixMatch.index === 0) ? column - prefixMatch.index - prefixMatch[0].length : column;
+    },
+
+    wordEnd: function(lineNumber, column, gapless)
+    {
+        var line = this._lines[lineNumber];
+        var suffix = line.substring(column);
+        var suffixMatch = this._noPunctuationRegex.exec(suffix);
+        return suffixMatch && (!gapless || suffixMatch.index === 0) ? column + suffixMatch.index + suffixMatch[0].length : column;
+    },
+
+    copyRange: function(range)
+    {
+        if (!range)
+            range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);
+
+        var clip = [];
+        if (range.startLine === range.endLine) {
+            clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn));
+            return clip.join("\n");
+        }
+        clip.push(this._lines[range.startLine].substring(range.startColumn));
+        for (var i = range.startLine + 1; i < range.endLine; ++i)
+            clip.push(this._lines[i]);
+        clip.push(this._lines[range.endLine].substring(0, range.endColumn));
+        return clip.join("\n");
+    },
+
+    setAttribute: function(line, name, value)
+    {
+        var attrs = this._attributes[line];
+        if (!attrs) {
+            attrs = {};
+            this._attributes[line] = attrs;
+        }
+        attrs[name] = value;
+    },
+
+    getAttribute: function(line, name)
+    {
+        var attrs = this._attributes[line];
+        return attrs ? attrs[name] : null;
+    },
+
+    removeAttribute: function(line, name)
+    {
+        var attrs = this._attributes[line];
+        if (attrs)
+            delete attrs[name];
+    },
+
+    _pushUndoableCommand: function(range, text)
+    {
+        var command = {
+            text: this.copyRange(range),
+            startLine: range.startLine,
+            startColumn: range.startColumn,
+            endLine: range.startLine,
+            endColumn: range.startColumn
+        };
+        if (this._inUndo)
+            this._redoStack.push(command);
+        else {
+            if (!this._inRedo)
+                this._redoStack = [];
+            this._undoStack.push(command);
+        }
+        return command;
+    },
+
+    undo: function()
+    {
+        this._markRedoableState();
+
+        this._inUndo = true;
+        var range = this._doUndo(this._undoStack);
+        delete this._inUndo;
+
+        return range;
+    },
+
+    redo: function()
+    {
+        this.markUndoableState();
+
+        this._inRedo = true;
+        var range = this._doUndo(this._redoStack);
+        delete this._inRedo;
+
+        return range;
+    },
+
+    _doUndo: function(stack)
+    {
+        var range = null;
+        for (var i = stack.length - 1; i >= 0; --i) {
+            var command = stack[i];
+            stack.length = i;
+
+            range = this.setText(command.range, command.text);
+            if (i > 0 && stack[i - 1].explicit)
+                return range;
+        }
+        return range;
+    },
+
+    markUndoableState: function()
+    {
+        if (this._undoStack.length)
+            this._undoStack[this._undoStack.length - 1].explicit = true;
+    },
+
+    _markRedoableState: function()
+    {
+        if (this._redoStack.length)
+            this._redoStack[this._redoStack.length - 1].explicit = true;
+    },
+
+    resetUndoStack: function()
+    {
+        this._undoStack = [];
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js
new file mode 100644
index 0000000..36a38cc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextPrompt = function(element, completions, stopCharacters, omitHistory)
+{
+    this.element = element;
+    this.element.addStyleClass("text-prompt");
+    this.completions = completions;
+    this.completionStopCharacters = stopCharacters;
+    if (!omitHistory) {
+        this.history = [];
+        this.historyOffset = 0;
+    }
+    this._boundOnKeyDown = this._onKeyDown.bind(this);
+    this.element.addEventListener("keydown", this._boundOnKeyDown, true);
+}
+
+WebInspector.TextPrompt.prototype = {
+    get text()
+    {
+        return this.element.textContent;
+    },
+
+    set text(x)
+    {
+        if (!x) {
+            // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
+            this.element.removeChildren();
+            this.element.appendChild(document.createElement("br"));
+        } else
+            this.element.textContent = x;
+
+        this.moveCaretToEndOfPrompt();
+    },
+
+    removeFromElement: function()
+    {
+        this.clearAutoComplete(true);
+        this.element.removeEventListener("keydown", this._boundOnKeyDown, true);
+    },
+
+    _onKeyDown: function(event)
+    {
+        function defaultAction()
+        {
+            this.clearAutoComplete();
+            this.autoCompleteSoon();
+        }
+
+        if (event.handled)
+            return;
+
+        var handled = false;
+
+        switch (event.keyIdentifier) {
+            case "Up":
+                this.upKeyPressed(event);
+                break;
+            case "Down":
+                this.downKeyPressed(event);
+                break;
+            case "U+0009": // Tab
+                this.tabKeyPressed(event);
+                break;
+            case "Right":
+            case "End":
+                if (!this.acceptAutoComplete())
+                    this.autoCompleteSoon();
+                break;
+            case "Alt":
+            case "Meta":
+            case "Shift":
+            case "Control":
+                break;
+            case "U+0050": // Ctrl+P = Previous
+                if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
+                    handled = true;
+                    this._moveBackInHistory();
+                    break;
+                }
+                defaultAction.call(this);
+                break;
+            case "U+004E": // Ctrl+N = Next
+                if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
+                    handled = true;
+                    this._moveForwardInHistory();
+                    break;
+                }
+                defaultAction.call(this);
+                break;
+            default:
+                defaultAction.call(this);
+                break;
+        }
+
+        handled |= event.handled;
+        if (handled) {
+            event.handled = true;
+            event.preventDefault();
+            event.stopPropagation();
+        }
+    },
+
+    acceptAutoComplete: function()
+    {
+        if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
+            return false;
+
+        var text = this.autoCompleteElement.textContent;
+        var textNode = document.createTextNode(text);
+        this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
+        delete this.autoCompleteElement;
+
+        var finalSelectionRange = document.createRange();
+        finalSelectionRange.setStart(textNode, text.length);
+        finalSelectionRange.setEnd(textNode, text.length);
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+
+        return true;
+    },
+
+    clearAutoComplete: function(includeTimeout)
+    {
+        if (includeTimeout && "_completeTimeout" in this) {
+            clearTimeout(this._completeTimeout);
+            delete this._completeTimeout;
+        }
+
+        if (!this.autoCompleteElement)
+            return;
+
+        if (this.autoCompleteElement.parentNode)
+            this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
+        delete this.autoCompleteElement;
+
+        if (!this._userEnteredRange || !this._userEnteredText)
+            return;
+
+        this._userEnteredRange.deleteContents();
+        this.element.pruneEmptyTextNodes();
+
+        var userTextNode = document.createTextNode(this._userEnteredText);
+        this._userEnteredRange.insertNode(userTextNode);
+
+        var selectionRange = document.createRange();
+        selectionRange.setStart(userTextNode, this._userEnteredText.length);
+        selectionRange.setEnd(userTextNode, this._userEnteredText.length);
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        delete this._userEnteredRange;
+        delete this._userEnteredText;
+    },
+
+    autoCompleteSoon: function()
+    {
+        if (!("_completeTimeout" in this))
+            this._completeTimeout = setTimeout(this.complete.bind(this, true), 250);
+    },
+
+    complete: function(auto, reverse)
+    {
+        this.clearAutoComplete(true);
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        var isEmptyInput = selectionRange.commonAncestorContainer === this.element; // this.element has no child Text nodes.
+
+        // Do not attempt to auto-complete an empty input in the auto mode (only on demand).
+        if (auto && isEmptyInput)
+            return;
+        if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this.element))
+            return;
+        if (auto && !this.isCaretAtEndOfPrompt())
+            return;
+        var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
+        this.completions(wordPrefixRange, auto, this._completionsReady.bind(this, selection, auto, wordPrefixRange, reverse));
+    },
+
+    _completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions)
+    {
+        if (!completions || !completions.length)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+
+        var fullWordRange = document.createRange();
+        fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset);
+        fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+
+        if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString())
+            return;
+
+        var wordPrefixLength = originalWordPrefixRange.toString().length;
+
+        if (auto)
+            var completionText = completions[0];
+        else {
+            if (completions.length === 1) {
+                var completionText = completions[0];
+                wordPrefixLength = completionText.length;
+            } else {
+                var commonPrefix = completions[0];
+                for (var i = 0; i < completions.length; ++i) {
+                    var completion = completions[i];
+                    var lastIndex = Math.min(commonPrefix.length, completion.length);
+                    for (var j = wordPrefixLength; j < lastIndex; ++j) {
+                        if (commonPrefix[j] !== completion[j]) {
+                            commonPrefix = commonPrefix.substr(0, j);
+                            break;
+                        }
+                    }
+                }
+                wordPrefixLength = commonPrefix.length;
+
+                if (selection.isCollapsed)
+                    var completionText = completions[0];
+                else {
+                    var currentText = fullWordRange.toString();
+
+                    var foundIndex = null;
+                    for (var i = 0; i < completions.length; ++i) {
+                        if (completions[i] === currentText)
+                            foundIndex = i;
+                    }
+
+                    var nextIndex = foundIndex + (reverse ? -1 : 1);
+                    if (foundIndex === null || nextIndex >= completions.length)
+                        var completionText = completions[0];
+                    else if (nextIndex < 0)
+                        var completionText = completions[completions.length - 1];
+                    else
+                        var completionText = completions[nextIndex];
+                }
+            }
+        }
+
+        this._userEnteredRange = fullWordRange;
+        this._userEnteredText = fullWordRange.toString();
+
+        fullWordRange.deleteContents();
+        this.element.pruneEmptyTextNodes();
+
+        var finalSelectionRange = document.createRange();
+
+        if (auto) {
+            var prefixText = completionText.substring(0, wordPrefixLength);
+            var suffixText = completionText.substring(wordPrefixLength);
+
+            var prefixTextNode = document.createTextNode(prefixText);
+            fullWordRange.insertNode(prefixTextNode);
+
+            this.autoCompleteElement = document.createElement("span");
+            this.autoCompleteElement.className = "auto-complete-text";
+            this.autoCompleteElement.textContent = suffixText;
+
+            prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+
+            finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+            finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+        } else {
+            var completionTextNode = document.createTextNode(completionText);
+            fullWordRange.insertNode(completionTextNode);
+
+            if (completions.length > 1)
+                finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
+            else
+                finalSelectionRange.setStart(completionTextNode, completionText.length);
+
+            finalSelectionRange.setEnd(completionTextNode, completionText.length);
+        }
+
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+    },
+
+    isCaretInsidePrompt: function()
+    {
+        return this.element.isInsertionCaretInside();
+    },
+
+    isCaretAtEndOfPrompt: function()
+    {
+        var selection = window.getSelection();
+        if (!selection.rangeCount || !selection.isCollapsed)
+            return false;
+
+        var selectionRange = selection.getRangeAt(0);
+        var node = selectionRange.startContainer;
+        if (node !== this.element && !node.isDescendant(this.element))
+            return false;
+
+        if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+            return false;
+
+        var foundNextText = false;
+        while (node) {
+            if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
+                if (foundNextText)
+                    return false;
+                foundNextText = true;
+            }
+
+            node = node.traverseNextNode(this.element);
+        }
+
+        return true;
+    },
+
+    isCaretOnFirstLine: function()
+    {
+        var selection = window.getSelection();
+        var focusNode = selection.focusNode;
+        if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
+            return true;
+
+        if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1)
+            return false;
+        focusNode = focusNode.previousSibling;
+
+        while (focusNode) {
+            if (focusNode.nodeType !== Node.TEXT_NODE)
+                return true;
+            if (focusNode.textContent.indexOf("\n") !== -1)
+                return false;
+            focusNode = focusNode.previousSibling;
+        }
+
+        return true;
+    },
+
+    isCaretOnLastLine: function()
+    {
+        var selection = window.getSelection();
+        var focusNode = selection.focusNode;
+        if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
+            return true;
+
+        if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1)
+            return false;
+        focusNode = focusNode.nextSibling;
+
+        while (focusNode) {
+            if (focusNode.nodeType !== Node.TEXT_NODE)
+                return true;
+            if (focusNode.textContent.indexOf("\n") !== -1)
+                return false;
+            focusNode = focusNode.nextSibling;
+        }
+
+        return true;
+    },
+
+    moveCaretToEndOfPrompt: function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+
+        var offset = this.element.childNodes.length;
+        selectionRange.setStart(this.element, offset);
+        selectionRange.setEnd(this.element, offset);
+
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+    },
+
+    tabKeyPressed: function(event)
+    {
+        event.handled = true;
+        this.complete(false, event.shiftKey);
+    },
+
+    upKeyPressed: function(event)
+    {
+        if (!this.isCaretOnFirstLine())
+            return;
+
+        event.handled = true;
+        this._moveBackInHistory();
+    },
+
+    downKeyPressed: function(event)
+    {
+        if (!this.isCaretOnLastLine())
+            return;
+
+        event.handled = true;
+        this._moveForwardInHistory();
+    },
+
+    _moveBackInHistory: function()
+    {
+        if (!this.history || this.historyOffset == this.history.length)
+            return;
+
+        this.clearAutoComplete(true);
+
+        if (this.historyOffset === 0)
+            this.tempSavedCommand = this.text;
+
+        ++this.historyOffset;
+        this.text = this.history[this.history.length - this.historyOffset];
+
+        this.element.scrollIntoView(true);
+        var firstNewlineIndex = this.text.indexOf("\n");
+        if (firstNewlineIndex === -1)
+            this.moveCaretToEndOfPrompt();
+        else {
+            var selection = window.getSelection();
+            var selectionRange = document.createRange();
+
+            selectionRange.setStart(this.element.firstChild, firstNewlineIndex);
+            selectionRange.setEnd(this.element.firstChild, firstNewlineIndex);
+
+            selection.removeAllRanges();
+            selection.addRange(selectionRange);
+        }
+    },
+
+    _moveForwardInHistory: function()
+    {
+        if (!this.history || this.historyOffset === 0)
+            return;
+
+        this.clearAutoComplete(true);
+
+        --this.historyOffset;
+
+        if (this.historyOffset === 0) {
+            this.text = this.tempSavedCommand;
+            delete this.tempSavedCommand;
+            return;
+        }
+
+        this.text = this.history[this.history.length - this.historyOffset];
+        this.element.scrollIntoView();
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextViewer.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextViewer.js
new file mode 100644
index 0000000..1bddbfc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextViewer.js
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextViewer = function(textModel, platform, url)
+{
+    this._textModel = textModel;
+    this._textModel.changeListener = this._textChanged.bind(this);
+
+    this.element = document.createElement("div");
+    this.element.className = "text-editor monospace";
+
+    var syncScrollListener = this._syncScroll.bind(this);
+    var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this);
+    this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener);
+    this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener);
+    this.element.appendChild(this._mainPanel.element);
+    this.element.appendChild(this._gutterPanel.element);
+}
+
+WebInspector.TextViewer.prototype = {
+    set mimeType(mimeType)
+    {
+        this._mainPanel.mimeType = mimeType;
+    },
+
+    set readOnly(readOnly)
+    {
+        this._mainPanel.readOnly = readOnly;
+    },
+
+    get textModel()
+    {
+        return this._textModel;
+    },
+
+    revealLine: function(lineNumber)
+    {
+        this._mainPanel.revealLine(lineNumber);
+    },
+
+    addDecoration: function(lineNumber, decoration)
+    {
+        this._mainPanel.addDecoration(lineNumber, decoration);
+        this._gutterPanel.addDecoration(lineNumber, decoration);
+    },
+
+    removeDecoration: function(lineNumber, decoration)
+    {
+        this._mainPanel.removeDecoration(lineNumber, decoration);
+        this._gutterPanel.removeDecoration(lineNumber, decoration);
+    },
+
+    markAndRevealRange: function(range)
+    {
+        this._mainPanel.markAndRevealRange(range);
+    },
+
+    highlightLine: function(lineNumber)
+    {
+        this._mainPanel.highlightLine(lineNumber);
+    },
+
+    clearLineHighlight: function()
+    {
+        this._mainPanel.clearLineHighlight();
+    },
+
+    freeCachedElements: function()
+    {
+        this._mainPanel.freeCachedElements();
+        this._gutterPanel.freeCachedElements();
+    },
+
+    editLine: function(lineRow, callback)
+    {
+        this._mainPanel.editLine(lineRow, callback);
+    },
+
+    get scrollTop()
+    {
+        return this._mainPanel.element.scrollTop;
+    },
+
+    set scrollTop(scrollTop)
+    {
+        this._mainPanel.element.scrollTop = scrollTop;
+    },
+
+    get scrollLeft()
+    {
+        return this._mainPanel.element.scrollLeft;
+    },
+
+    set scrollLeft(scrollLeft)
+    {
+        this._mainPanel.element.scrollLeft = scrollLeft;
+    },
+
+    beginUpdates: function()
+    {
+        this._mainPanel.beginUpdates();
+        this._gutterPanel.beginUpdates();
+    },
+
+    endUpdates: function()
+    {
+        this._mainPanel.endUpdates();
+        this._gutterPanel.endUpdates();
+    },
+
+    resize: function()
+    {
+        this._mainPanel.resize();
+        this._gutterPanel.resize();
+        this._updatePanelOffsets();
+    },
+
+    // WebInspector.TextModel listener
+    _textChanged: function(oldRange, newRange, oldText, newText)
+    {
+        this._mainPanel.textChanged();
+        this._gutterPanel.textChanged();
+        this._updatePanelOffsets();
+    },
+
+    _updatePanelOffsets: function()
+    {
+        var lineNumbersWidth = this._gutterPanel.element.offsetWidth;
+        if (lineNumbersWidth)
+            this._mainPanel.element.style.setProperty("left", lineNumbersWidth + "px");
+        else
+            this._mainPanel.element.style.removeProperty("left"); // Use default value set in CSS.
+    },
+
+    _syncScroll: function()
+    {
+        // Async call due to performance reasons.
+        setTimeout(function() {
+            var mainElement = this._mainPanel.element;
+            var gutterElement = this._gutterPanel.element;
+
+            // Handle horizontal scroll bar at the bottom of the main panel.
+            if (gutterElement.offsetHeight > mainElement.clientHeight)
+                gutterElement.style.setProperty("padding-bottom", (gutterElement.offsetHeight - mainElement.clientHeight) + "px");
+            else
+                gutterElement.style.removeProperty("padding-bottom");
+
+            gutterElement.scrollTop = mainElement.scrollTop;
+        }.bind(this), 0);
+    },
+
+    _syncDecorationsForLine: function(lineNumber)
+    {
+        if (lineNumber >= this._textModel.linesCount)
+            return;
+
+        var mainChunk = this._mainPanel.makeLineAChunk(lineNumber);
+        var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
+        var height = mainChunk.height;
+        if (height)
+            gutterChunk.element.style.setProperty("height", height + "px");
+        else
+            gutterChunk.element.style.removeProperty("height");
+    }
+}
+
+WebInspector.TextEditorChunkedPanel = function(textModel)
+{
+    this._textModel = textModel;
+
+    this._defaultChunkSize = 50;
+    this._paintCoalescingLevel = 0;
+    this._domUpdateCoalescingLevel = 0;
+}
+
+WebInspector.TextEditorChunkedPanel.prototype = {
+    get textModel()
+    {
+        return this._textModel;
+    },
+
+    revealLine: function(lineNumber)
+    {
+        if (lineNumber >= this._textModel.linesCount)
+            return;
+
+        var chunk = this.makeLineAChunk(lineNumber);
+        chunk.element.scrollIntoViewIfNeeded();
+    },
+
+    addDecoration: function(lineNumber, decoration)
+    {
+        var chunk = this.makeLineAChunk(lineNumber);
+        chunk.addDecoration(decoration);
+    },
+
+    removeDecoration: function(lineNumber, decoration)
+    {
+        var chunk = this.makeLineAChunk(lineNumber);
+        chunk.removeDecoration(decoration);
+    },
+
+    textChanged: function(oldRange, newRange, oldText, newText)
+    {
+        this._buildChunks();
+    },
+
+    _buildChunks: function()
+    {
+        this.beginDomUpdates();
+
+        this.element.removeChildren();
+
+        this._textChunks = [];
+        for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) {
+            var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
+            this._textChunks.push(chunk);
+            this.element.appendChild(chunk.element);
+        }
+
+        this._repaintAll();
+
+        this.endDomUpdates();
+    },
+
+    makeLineAChunk: function(lineNumber)
+    {
+        if (!this._textChunks)
+            this._buildChunks();
+
+        var chunkNumber = this._chunkNumberForLine(lineNumber);
+        var oldChunk = this._textChunks[chunkNumber];
+        if (oldChunk.linesCount === 1)
+            return oldChunk;
+
+        this.beginDomUpdates();
+
+        var wasExpanded = oldChunk.expanded;
+        oldChunk.expanded = false;
+
+        var insertIndex = chunkNumber + 1;
+
+        // Prefix chunk.
+        if (lineNumber > oldChunk.startLine) {
+            var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber);
+            this._textChunks.splice(insertIndex++, 0, prefixChunk);
+            this.element.insertBefore(prefixChunk.element, oldChunk.element);
+        }
+
+        // Line chunk.
+        var lineChunk = this._createNewChunk(lineNumber, lineNumber + 1);
+        this._textChunks.splice(insertIndex++, 0, lineChunk);
+        this.element.insertBefore(lineChunk.element, oldChunk.element);
+
+        // Suffix chunk.
+        if (oldChunk.startLine + oldChunk.linesCount > lineNumber + 1) {
+            var suffixChunk = this._createNewChunk(lineNumber + 1, oldChunk.startLine + oldChunk.linesCount);
+            this._textChunks.splice(insertIndex, 0, suffixChunk);
+            this.element.insertBefore(suffixChunk.element, oldChunk.element);
+        }
+
+        // Remove enclosing chunk.
+        this._textChunks.splice(chunkNumber, 1);
+        this.element.removeChild(oldChunk.element);
+
+        if (wasExpanded) {
+            if (prefixChunk)
+                prefixChunk.expanded = true;
+            lineChunk.expanded = true;
+            if (suffixChunk)
+                suffixChunk.expanded = true;
+        }
+
+        this.endDomUpdates();
+
+        return lineChunk;
+    },
+
+    _scroll: function()
+    {
+        this._scheduleRepaintAll();
+        if (this._syncScrollListener)
+            this._syncScrollListener();
+    },
+
+    _scheduleRepaintAll: function()
+    {
+        if (this._repaintAllTimer)
+            clearTimeout(this._repaintAllTimer);
+        this._repaintAllTimer = setTimeout(this._repaintAll.bind(this), 50);
+    },
+
+    beginUpdates: function()
+    {
+        this._paintCoalescingLevel++;
+    },
+
+    endUpdates: function()
+    {
+        this._paintCoalescingLevel--;
+        if (!this._paintCoalescingLevel)
+            this._repaintAll();
+    },
+
+    beginDomUpdates: function()
+    {
+        this._domUpdateCoalescingLevel++;
+    },
+
+    endDomUpdates: function()
+    {
+        this._domUpdateCoalescingLevel--;
+    },
+
+    _chunkNumberForLine: function(lineNumber)
+    {
+        for (var i = 0; i < this._textChunks.length; ++i) {
+            var line = this._textChunks[i].startLine;
+            if (lineNumber >= line && lineNumber < line + this._textChunks[i].linesCount)
+                return i;
+        }
+        return this._textChunks.length - 1;
+    },
+
+    _chunkForLine: function(lineNumber)
+    {
+        return this._textChunks[this._chunkNumberForLine(lineNumber)];
+    },
+
+    _repaintAll: function()
+    {
+        delete this._repaintAllTimer;
+
+        if (this._paintCoalescingLevel || this._dirtyLines)
+            return;
+
+        if (!this._textChunks)
+            this._buildChunks();
+
+        var visibleFrom = this.element.scrollTop;
+        var visibleTo = this.element.scrollTop + this.element.clientHeight;
+
+        var offset = 0;
+        var fromIndex = -1;
+        var toIndex = 0;
+        for (var i = 0; i < this._textChunks.length; ++i) {
+            var chunk = this._textChunks[i];
+            var chunkHeight = chunk.height;
+            if (offset + chunkHeight > visibleFrom && offset < visibleTo) {
+                if (fromIndex === -1)
+                    fromIndex = i;
+                toIndex = i + 1;
+            } else {
+                if (offset >= visibleTo)
+                    break;
+            }
+            offset += chunkHeight;
+        }
+
+        if (toIndex)
+            this._expandChunks(fromIndex, toIndex);
+    },
+
+    _totalHeight: function(firstElement, lastElement)
+    {
+        lastElement = (lastElement || firstElement).nextElementSibling;
+        if (lastElement)
+            return lastElement.offsetTop - firstElement.offsetTop;
+        else if (firstElement.offsetParent)
+            return firstElement.offsetParent.scrollHeight - firstElement.offsetTop;
+        return firstElement.offsetHeight;
+    },
+    
+    resize: function()
+    {
+        this._repaintAll();
+    }
+}
+
+WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineListener)
+{
+    WebInspector.TextEditorChunkedPanel.call(this, textModel);
+
+    this._syncDecorationsForLineListener = syncDecorationsForLineListener;
+
+    this.element = document.createElement("div");
+    this.element.className = "text-editor-lines";
+
+    this.element.addEventListener("scroll", this._scroll.bind(this), false);
+
+    this.freeCachedElements();
+    this._buildChunks();
+}
+
+WebInspector.TextEditorGutterPanel.prototype = {
+    freeCachedElements: function()
+    {
+        this._cachedRows = [];
+    },
+
+    _createNewChunk: function(startLine, endLine)
+    {
+        return new WebInspector.TextEditorGutterChunk(this, startLine, endLine);
+    },
+
+    _expandChunks: function(fromIndex, toIndex)
+    {
+        for (var i = 0; i < this._textChunks.length; ++i) {
+            this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
+        }
+    }
+}
+
+WebInspector.TextEditorGutterPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype;
+
+WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
+{
+    this._textViewer = textViewer;
+    this._textModel = textViewer._textModel;
+
+    this.startLine = startLine;
+    endLine = Math.min(this._textModel.linesCount, endLine);
+    this.linesCount = endLine - startLine;
+
+    this._expanded = false;
+
+    this.element = document.createElement("div");
+    this.element.lineNumber = startLine;
+    this.element.className = "webkit-line-number";
+
+    if (this.linesCount === 1) {
+        // Single line chunks are typically created for decorations. Host line number in
+        // the sub-element in order to allow flexible border / margin management.
+        var innerSpan = document.createElement("span");
+        innerSpan.className = "webkit-line-number-inner";
+        innerSpan.textContent = startLine + 1;
+        var outerSpan = document.createElement("div");
+        outerSpan.className = "webkit-line-number-outer";
+        outerSpan.appendChild(innerSpan);
+        this.element.appendChild(outerSpan);
+    } else {
+        var lineNumbers = [];
+        for (var i = startLine; i < endLine; ++i) {
+            lineNumbers.push(i + 1);
+        }
+        this.element.textContent = lineNumbers.join("\n");
+    }
+}
+
+WebInspector.TextEditorGutterChunk.prototype = {
+    addDecoration: function(decoration)
+    {
+        if (typeof decoration === "string") {
+            this.element.addStyleClass(decoration);
+        }
+    },
+
+    removeDecoration: function(decoration)
+    {
+        if (typeof decoration === "string") {
+            this.element.removeStyleClass(decoration);
+        }
+    },
+
+    get expanded()
+    {
+        return this._expanded;
+    },
+
+    set expanded(expanded)
+    {
+        if (this.linesCount === 1)
+            this._textViewer._syncDecorationsForLineListener(this.startLine);
+
+        if (this._expanded === expanded)
+            return;
+
+        this._expanded = expanded;
+
+        if (this.linesCount === 1)
+            return;
+
+        this._textViewer.beginDomUpdates();
+
+        if (expanded) {
+            this._expandedLineRows = [];
+            var parentElement = this.element.parentElement;
+            for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) {
+                var lineRow = this._createRow(i);
+                parentElement.insertBefore(lineRow, this.element);
+                this._expandedLineRows.push(lineRow);
+            }
+            parentElement.removeChild(this.element);
+        } else {
+            var elementInserted = false;
+            for (var i = 0; i < this._expandedLineRows.length; ++i) {
+                var lineRow = this._expandedLineRows[i];
+                var parentElement = lineRow.parentElement;
+                if (parentElement) {
+                    if (!elementInserted) {
+                        elementInserted = true;
+                        parentElement.insertBefore(this.element, lineRow);
+                    }
+                    parentElement.removeChild(lineRow);
+                }
+                this._textViewer._cachedRows.push(lineRow);
+            }
+            delete this._expandedLineRows;
+        }
+
+        this._textViewer.endDomUpdates();
+    },
+
+    get height()
+    {
+        if (!this._expandedLineRows)
+            return this._textViewer._totalHeight(this.element);
+        return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
+    },
+
+    _createRow: function(lineNumber)
+    {
+        var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
+        lineRow.lineNumber = lineNumber;
+        lineRow.className = "webkit-line-number";
+        lineRow.textContent = lineNumber + 1;
+        return lineRow;
+    }
+}
+
+WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener)
+{
+    WebInspector.TextEditorChunkedPanel.call(this, textModel);
+
+    this._syncScrollListener = syncScrollListener;
+    this._syncDecorationsForLineListener = syncDecorationsForLineListener;
+
+    this._url = url;
+    this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this));
+    this._readOnly = true;
+
+    this.element = document.createElement("div");
+    this.element.className = "text-editor-contents";
+    this.element.tabIndex = 0;
+
+    this.element.addEventListener("scroll", this._scroll.bind(this), false);
+
+    // FIXME: Remove old live editing functionality and Preferences.sourceEditorEnabled flag.
+    if (!Preferences.sourceEditorEnabled)
+        this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
+
+    var handleDOMUpdates = this._handleDOMUpdates.bind(this);
+    this.element.addEventListener("DOMCharacterDataModified", handleDOMUpdates, false);
+    this.element.addEventListener("DOMNodeInserted", handleDOMUpdates, false);
+    this.element.addEventListener("DOMNodeRemoved", handleDOMUpdates, false);
+    // For some reasons, in a few corner cases the events above are not able to catch the editings.
+    // To workaround that we also listen to a more general event as a backup.
+    this.element.addEventListener("DOMSubtreeModified", this._handleDOMSubtreeModified.bind(this), false);
+
+    this.freeCachedElements();
+    this._buildChunks();
+}
+
+WebInspector.TextEditorMainPanel.prototype = {
+    set mimeType(mimeType)
+    {
+        this._highlighter.mimeType = mimeType;
+    },
+
+    set readOnly(readOnly)
+    {
+        // FIXME: Remove the Preferences.sourceEditorEnabled flag.
+        if (!Preferences.sourceEditorEnabled)
+            return;
+
+        this._readOnly = readOnly;
+        if (this._readOnly)
+            this.element.removeStyleClass("text-editor-editable");
+        else
+            this.element.addStyleClass("text-editor-editable");
+    },
+
+    markAndRevealRange: function(range)
+    {
+        if (this._rangeToMark) {
+            var markedLine = this._rangeToMark.startLine;
+            this._rangeToMark = null;
+            this._paintLines(markedLine, markedLine + 1);
+        }
+
+        if (range) {
+            this._rangeToMark = range;
+            this.revealLine(range.startLine);
+            this._paintLines(range.startLine, range.startLine + 1);
+            if (this._markedRangeElement)
+                this._markedRangeElement.scrollIntoViewIfNeeded();
+        }
+        delete this._markedRangeElement;
+    },
+
+    highlightLine: function(lineNumber)
+    {
+        this.clearLineHighlight();
+        this._highlightedLine = lineNumber;
+        this.revealLine(lineNumber);
+        this.addDecoration(lineNumber, "webkit-highlighted-line");
+    },
+
+    clearLineHighlight: function()
+    {
+        if (typeof this._highlightedLine === "number") {
+            this.removeDecoration(this._highlightedLine, "webkit-highlighted-line");
+            delete this._highlightedLine;
+        }
+    },
+
+    freeCachedElements: function()
+    {
+        this._cachedSpans = [];
+        this._cachedTextNodes = [];
+        this._cachedRows = [];
+    },
+
+    _handleKeyDown: function()
+    {
+        if (this._editingLine || event.metaKey || event.shiftKey || event.ctrlKey || event.altKey)
+            return;
+
+        var scrollValue = 0;
+        if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Up.code)
+            scrollValue = -1;
+        else if (event.keyCode == WebInspector.KeyboardShortcut.Keys.Down.code)
+            scrollValue = 1;
+
+        if (scrollValue) {
+            event.preventDefault();
+            event.stopPropagation();
+            this.element.scrollByLines(scrollValue);
+            return;
+        }
+
+        scrollValue = 0;
+        if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Left.code)
+            scrollValue = -40;
+        else if (event.keyCode == WebInspector.KeyboardShortcut.Keys.Right.code)
+            scrollValue = 40;
+
+        if (scrollValue) {
+            event.preventDefault();
+            event.stopPropagation();
+            this.element.scrollLeft += scrollValue;
+        }
+    },
+
+    editLine: function(lineRow, callback)
+    {
+        var oldContent = lineRow.innerHTML;
+        function finishEditing(committed, e, newContent)
+        {
+            if (committed)
+                callback(newContent);
+            lineRow.innerHTML = oldContent;
+            delete this._editingLine;
+        }
+        this._editingLine = WebInspector.startEditing(lineRow, {
+            context: null,
+            commitHandler: finishEditing.bind(this, true),
+            cancelHandler: finishEditing.bind(this, false),
+            multiline: true
+        });
+    },
+
+    _buildChunks: function()
+    {
+        this._highlighter.reset();
+        for (var i = 0; i < this._textModel.linesCount; ++i)
+            this._textModel.removeAttribute(i, "highlight");
+
+        WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this);
+    },
+
+    _createNewChunk: function(startLine, endLine)
+    {
+        return new WebInspector.TextEditorMainChunk(this, startLine, endLine);
+    },
+
+    _expandChunks: function(fromIndex, toIndex)
+    {
+        var lastChunk = this._textChunks[toIndex - 1];
+        var lastVisibleLine = lastChunk.startLine + lastChunk.linesCount;
+
+        var selection = this._getSelection();
+
+        this._muteHighlightListener = true;
+        this._highlighter.highlight(lastVisibleLine);
+        delete this._muteHighlightListener;
+
+        for (var i = 0; i < this._textChunks.length; ++i) {
+            this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
+        }
+
+        this._restoreSelection(selection);
+    },
+
+    _highlightDataReady: function(fromLine, toLine)
+    {
+        if (this._muteHighlightListener || this._dirtyLines)
+            return;
+        this._paintLines(fromLine, toLine, true /*restoreSelection*/);
+    },
+
+    _paintLines: function(fromLine, toLine, restoreSelection)
+    {
+        var selection;
+        var chunk = this._chunkForLine(fromLine);
+        for (var i = fromLine; i < toLine; ++i) {
+            if (i >= chunk.startLine + chunk.linesCount)
+                chunk = this._chunkForLine(i);
+            var lineRow = chunk.getExpandedLineRow(i);
+            if (!lineRow)
+                continue;
+            if (restoreSelection && !selection)
+                selection = this._getSelection();
+            this._paintLine(lineRow, i);
+        }
+        if (restoreSelection)
+            this._restoreSelection(selection);
+    },
+
+    _paintLine: function(lineRow, lineNumber)
+    {
+        this.beginDomUpdates();
+        try {
+            var highlight = this._textModel.getAttribute(lineNumber, "highlight");
+            if (!highlight) {
+                if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+                    this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+                return;
+            }
+
+            lineRow.removeChildren();
+            var line = this._textModel.line(lineNumber);
+            if (!line)
+                lineRow.appendChild(document.createElement("br"));
+
+            var plainTextStart = -1;
+            for (var j = 0; j < line.length;) {
+                if (j > 1000) {
+                    // This line is too long - do not waste cycles on minified js highlighting.
+                    if (plainTextStart === -1)
+                        plainTextStart = j;
+                    break;
+                }
+                var attribute = highlight[j];
+                if (!attribute || !attribute.tokenType) {
+                    if (plainTextStart === -1)
+                        plainTextStart = j;
+                    j++;
+                } else {
+                    if (plainTextStart !== -1) {
+                        this._appendTextNode(lineRow, line.substring(plainTextStart, j));
+                        plainTextStart = -1;
+                    }
+                    this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
+                    j += attribute.length;
+                }
+            }
+            if (plainTextStart !== -1)
+                this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
+            if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+                this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+            if (lineRow.decorationsElement)
+                lineRow.appendChild(lineRow.decorationsElement);
+        } finally {
+            this.endDomUpdates();
+        }
+    },
+
+    _releaseLinesHighlight: function(lineRow)
+    {
+        if (!lineRow)
+            return;
+        if ("spans" in lineRow) {
+            var spans = lineRow.spans;
+            for (var j = 0; j < spans.length; ++j)
+                this._cachedSpans.push(spans[j]);
+            delete lineRow.spans;
+        }
+        if ("textNodes" in lineRow) {
+            var textNodes = lineRow.textNodes;
+            for (var j = 0; j < textNodes.length; ++j)
+                this._cachedTextNodes.push(textNodes[j]);
+            delete lineRow.textNodes;
+        }
+        this._cachedRows.push(lineRow);
+    },
+
+    _getSelection: function()
+    {
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return null;
+        var selectionRange = selection.getRangeAt(0);
+        // Selection may be outside of the viewer.
+        if (!this.element.isAncestor(selectionRange.startContainer) || !this.element.isAncestor(selectionRange.endContainer))
+            return null;
+        var start = this._selectionToPosition(selectionRange.startContainer, selectionRange.startOffset);
+        var end = selectionRange.collapsed ? start : this._selectionToPosition(selectionRange.endContainer, selectionRange.endOffset);
+        if (selection.anchorNode === selectionRange.startContainer && selection.anchorOffset === selectionRange.startOffset)
+            return new WebInspector.TextRange(start.line, start.column, end.line, end.column);
+        else
+            return new WebInspector.TextRange(end.line, end.column, start.line, start.column);
+    },
+
+    _restoreSelection: function(range)
+    {
+        if (!range)
+            return;
+        var start = this._positionToSelection(range.startLine, range.startColumn);
+        var end = range.isEmpty() ? start : this._positionToSelection(range.endLine, range.endColumn);
+        window.getSelection().setBaseAndExtent(start.container, start.offset, end.container, end.offset);
+    },
+
+    _selectionToPosition: function(container, offset)
+    {
+        if (container === this.element && offset === 0)
+            return { line: 0, column: 0 };
+        if (container === this.element && offset === 1)
+            return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) };
+
+        var lineRow = container.enclosingNodeOrSelfWithNodeName("DIV");
+        var lineNumber = lineRow.lineNumber;
+        if (container === lineRow && offset === 0)
+            return { line: lineNumber, column: 0 };
+
+        // This may be chunk and chunks may contain \n.
+        var column = 0;
+        var node = lineRow.traverseNextTextNode(lineRow);
+        while (node && node !== container) {
+            var text = node.textContent;
+            for (var i = 0; i < text.length; ++i) {
+                if (text.charAt(i) === "\n") {
+                    lineNumber++;
+                    column = 0;
+                } else
+                    column++;
+            }
+            node = node.traverseNextTextNode(lineRow);
+        }
+
+        if (node === container && offset) {
+            var text = node.textContent;
+            for (var i = 0; i < offset; ++i) {
+                if (text.charAt(i) === "\n") {
+                    lineNumber++;
+                    column = 0;
+                } else
+                    column++;
+            }
+        }
+        return { line: lineNumber, column: column };
+    },
+
+    _positionToSelection: function(line, column)
+    {
+        var chunk = this._chunkForLine(line);
+        var lineRow = chunk.getExpandedLineRow(line);
+        if (lineRow)
+            var rangeBoundary = lineRow.rangeBoundaryForOffset(column);
+        else {
+            var offset = column;
+            for (var i = chunk.startLine; i < line; ++i)
+                offset += this._textModel.lineLength(i) + 1; // \n
+            lineRow = chunk.element;
+            if (lineRow.firstChild)
+                var rangeBoundary = { container: lineRow.firstChild, offset: offset };
+            else
+                var rangeBoundary = { container: lineRow, offset: 0 };
+        }
+        return rangeBoundary;
+    },
+
+    _appendSpan: function(element, content, className)
+    {
+        if (className === "html-resource-link" || className === "html-external-link") {
+            element.appendChild(this._createLink(content, className === "html-external-link"));
+            return;
+        }
+
+        var span = this._cachedSpans.pop() || document.createElement("span");
+        span.className = "webkit-" + className;
+        span.textContent = content;
+        element.appendChild(span);
+        if (!("spans" in element))
+            element.spans = [];
+        element.spans.push(span);
+    },
+
+    _appendTextNode: function(element, text)
+    {
+        var textNode = this._cachedTextNodes.pop();
+        if (textNode)
+            textNode.nodeValue = text;
+        else
+            textNode = document.createTextNode(text);
+        element.appendChild(textNode);
+        if (!("textNodes" in element))
+            element.textNodes = [];
+        element.textNodes.push(textNode);
+    },
+
+    _createLink: function(content, isExternal)
+    {
+        var quote = content.charAt(0);
+        if (content.length > 1 && (quote === "\"" ||   quote === "'"))
+            content = content.substring(1, content.length - 1);
+        else
+            quote = null;
+
+        var a = WebInspector.linkifyURLAsNode(this._rewriteHref(content), content, null, isExternal);
+        var span = document.createElement("span");
+        span.className = "webkit-html-attribute-value";
+        if (quote)
+            span.appendChild(document.createTextNode(quote));
+        span.appendChild(a);
+        if (quote)
+            span.appendChild(document.createTextNode(quote));
+        return span;
+    },
+
+    _rewriteHref: function(hrefValue, isExternal)
+    {
+        if (!this._url || !hrefValue || hrefValue.indexOf("://") > 0)
+            return hrefValue;
+        return WebInspector.completeURL(this._url, hrefValue);
+    },
+
+    textChanged: function(oldRange, newRange, oldText, newText)
+    {
+        // FIXME: Update only that part of the editor that has just been changed.
+        this._buildChunks();
+    },
+
+    _handleDOMUpdates: function(e)
+    {
+        if (this._domUpdateCoalescingLevel)
+            return;
+
+        var target = e.target;
+        if (target === this.element)
+            return;
+
+        var lineRow = target.enclosingNodeOrSelfWithClass("webkit-line-content");
+        if (!lineRow)
+            return;
+
+        if (lineRow.decorationsElement && lineRow.decorationsElement.isAncestor(target)) {
+            if (this._syncDecorationsForLineListener) {
+                // Wait until this event is processed and only then sync the sizes. This is necessary in
+                // case of the DOMNodeRemoved event, because it is dispatched before the removal takes place.
+                setTimeout(function() {
+                    this._syncDecorationsForLineListener(lineRow.lineNumber);
+                }.bind(this), 0);
+            }
+            return;
+        }
+
+        if (this._readOnly)
+            return;
+
+        if (target === lineRow && (e.type === "DOMNodeInserted" || e.type === "DOMNodeRemoved")) {
+            // The "lineNumber" (if any) is no longer valid for a line being removed or inserted.
+            delete lineRow.lineNumber;
+        }
+
+        var startLine = 0;
+        for (var row = lineRow; row; row = row.previousSibling) {
+            if (typeof row.lineNumber === "number") {
+                startLine = row.lineNumber;
+                break;
+            }
+        }
+
+        var endLine = this._textModel.linesCount;
+        for (var row = lineRow.nextSibling; row; row = row.nextSibling) {
+            if (typeof row.lineNumber === "number") {
+                endLine = row.lineNumber;
+                break;
+            }
+        }
+
+        if (this._dirtyLines) {
+            this._dirtyLines.start = Math.min(this._dirtyLines.start, startLine);
+            this._dirtyLines.end = Math.max(this._dirtyLines.end, endLine);
+        } else {
+            this._dirtyLines = { start: startLine, end: endLine };
+            setTimeout(this._applyDomUpdates.bind(this), 0);
+        }
+    },
+
+    _handleDOMSubtreeModified: function(e)
+    {
+        if (this._domUpdateCoalescingLevel || this._readOnly || e.target !== this.element)
+            return;
+
+        // Proceed only when other events failed to catch the DOM updates, otherwise it is not necessary.
+        if (this._dirtyLines)
+            return;
+
+        var selection = this._getSelection();
+        if (!selection)
+            return;
+
+        var startLine = Math.min(selection.startLine, selection.endLine);
+        var endLine = Math.max(selection.startLine, selection.endLine) + 1;
+        endLine = Math.min(this._textModel.linesCount, endLine);
+
+        this._dirtyLines = { start: startLine, end: endLine };
+        setTimeout(this._applyDomUpdates.bind(this), 0);
+    },
+
+    _applyDomUpdates: function()
+    {
+        if (!this._dirtyLines)
+            return;
+
+        var dirtyLines = this._dirtyLines;
+        delete this._dirtyLines;
+
+        // Check if the editor had been set readOnly by the moment when this async callback got executed.
+        if (this._readOnly)
+            return;
+
+        // FIXME: DELETE DECORATIONS IN THE INVOLVED CHUNKS IF ANY! SYNC THE GUTTER ALSO.
+
+        // FIXME: DELETE MARKED AND HIGHLIGHTED LINES (INVALIDATE SEARCH RESULTS)! this._markedRangeElement
+        
+        var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start);
+        var startLine = this._textChunks[firstChunkNumber].startLine;
+        var endLine = this._textModel.linesCount;
+
+        // Collect lines.
+        var firstLineRow;
+        if (firstChunkNumber) {
+            var chunk = this._textChunks[firstChunkNumber - 1];
+            firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
+            firstLineRow = firstLineRow.nextSibling;
+        } else {
+            firstLineRow = this.element.firstChild;
+        }
+
+        var lines = [];
+        for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) {
+            if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) {
+                endLine = lineRow.lineNumber;
+                break;
+            }
+            // Update with the newest lineNumber, so that the call to the _getSelection method below should work.
+            lineRow.lineNumber = startLine + lines.length;
+            this._collectLinesFromDiv(lines, lineRow);
+        }
+
+        // Try to decrease the range being replaced if possible.
+        var startOffset = 0;
+        while (startLine < dirtyLines.start && startOffset < lines.length) {
+            if (this._textModel.line(startLine) !== lines[startOffset])
+                break;
+            ++startOffset;
+            ++startLine;
+        }
+
+        var endOffset = lines.length;
+        while (endLine > dirtyLines.end && endOffset > startOffset) {
+            if (this._textModel.line(endLine - 1) !== lines[endOffset - 1])
+                break;
+            --endOffset;
+            --endLine;
+        }
+
+        lines = lines.slice(startOffset, endOffset);
+
+        var selection = this._getSelection();
+        this.beginUpdates();
+
+        if (lines.length === 0 && endLine < this._textModel.linesCount) {
+            var range = new WebInspector.TextRange(startLine, 0, endLine, 0);
+            var newRange = this._textModel.setText(range, '');
+        } else {
+            var range = new WebInspector.TextRange(startLine, 0, endLine - 1, this._textModel.lineLength(endLine - 1));
+            var newRange = this._textModel.setText(range, lines.join("\n"));
+        }
+
+        this.endUpdates();
+        this._restoreSelection(selection);
+    },
+
+    _collectLinesFromDiv: function(lines, element)
+    {
+        var textContents = [];
+        var node = element.traverseNextNode(element);
+        while (node) {
+            if (node.nodeName.toLowerCase() === "br")
+                textContents.push("\n");
+            else if (node.nodeType === Node.TEXT_NODE)
+                textContents.push(node.textContent);
+            node = node.traverseNextNode(element);
+        }
+
+        var textContent = textContents.join('');
+        // The last \n (if any) does not "count" in a DIV.
+        textContent = textContent.replace(/\n$/, '');
+
+        textContents = textContent.split("\n");
+        for (var i = 0; i < textContents.length; ++i)
+            lines.push(textContents[i]);
+    }
+}
+
+WebInspector.TextEditorMainPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype;
+
+WebInspector.TextEditorMainChunk = function(textViewer, startLine, endLine)
+{
+    this._textViewer = textViewer;
+    this._textModel = textViewer._textModel;
+
+    this.element = document.createElement("div");
+    this.element.lineNumber = startLine;
+    this.element.className = "webkit-line-content";
+
+    this.startLine = startLine;
+    endLine = Math.min(this._textModel.linesCount, endLine);
+    this.linesCount = endLine - startLine;
+
+    this._expanded = false;
+
+    var lines = [];
+    for (var i = startLine; i < endLine; ++i) {
+        lines.push(this._textModel.line(i));
+    }
+
+    this.element.textContent = lines.join("\n");
+
+    // The last empty line will get swallowed otherwise.
+    if (!lines[lines.length - 1])
+        this.element.appendChild(document.createElement("br"));
+}
+
+WebInspector.TextEditorMainChunk.prototype = {
+    addDecoration: function(decoration)
+    {
+        if (typeof decoration === "string") {
+            this.element.addStyleClass(decoration);
+            return;
+        }
+        this._textViewer.beginDomUpdates();
+        if (!this.element.decorationsElement) {
+            this.element.decorationsElement = document.createElement("div");
+            this.element.decorationsElement.className = "webkit-line-decorations";
+            this.element.appendChild(this.element.decorationsElement);
+        }
+        this.element.decorationsElement.appendChild(decoration);
+        this._textViewer.endDomUpdates();
+    },
+
+    removeDecoration: function(decoration)
+    {
+        if (typeof decoration === "string") {
+            this.element.removeStyleClass(decoration);
+            return;
+        }
+        if (!this.element.decorationsElement)
+            return;
+        this._textViewer.beginDomUpdates();
+        this.element.decorationsElement.removeChild(decoration);
+        this._textViewer.endDomUpdates();
+    },
+
+    get expanded()
+    {
+        return this._expanded;
+    },
+
+    set expanded(expanded)
+    {
+        if (this._expanded === expanded)
+            return;
+
+        this._expanded = expanded;
+
+        if (this.linesCount === 1) {
+            if (expanded)
+                this._textViewer._paintLine(this.element, this.startLine);
+            return;
+        }
+
+        this._textViewer.beginDomUpdates();
+
+        if (expanded) {
+            this._expandedLineRows = [];
+            var parentElement = this.element.parentElement;
+            for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) {
+                var lineRow = this._createRow(i);
+                parentElement.insertBefore(lineRow, this.element);
+                this._expandedLineRows.push(lineRow);
+                this._textViewer._paintLine(lineRow, i);
+            }
+            parentElement.removeChild(this.element);
+        } else {
+            var elementInserted = false;
+            for (var i = 0; i < this._expandedLineRows.length; ++i) {
+                var lineRow = this._expandedLineRows[i];
+                var parentElement = lineRow.parentElement;
+                if (parentElement) {
+                    if (!elementInserted) {
+                        elementInserted = true;
+                        parentElement.insertBefore(this.element, lineRow);
+                    }
+                    parentElement.removeChild(lineRow);
+                }
+                this._textViewer._releaseLinesHighlight(lineRow);
+            }
+            delete this._expandedLineRows;
+        }
+
+        this._textViewer.endDomUpdates();
+    },
+
+    get height()
+    {
+        if (!this._expandedLineRows)
+            return this._textViewer._totalHeight(this.element);
+        return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
+    },
+
+    _createRow: function(lineNumber)
+    {
+        var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
+        lineRow.lineNumber = lineNumber;
+        lineRow.className = "webkit-line-content";
+        lineRow.textContent = this._textModel.line(lineNumber);
+        if (!lineRow.textContent)
+            lineRow.appendChild(document.createElement("br"));
+        return lineRow;
+    },
+
+    getExpandedLineRow: function(lineNumber)
+    {
+        if (!this._expanded || lineNumber < this.startLine || lineNumber >= this.startLine + this.linesCount)
+            return null;
+        if (!this._expandedLineRows)
+            return this.element;
+        return this._expandedLineRows[lineNumber - this.startLine];
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineAgent.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineAgent.js
new file mode 100644
index 0000000..97b8e42
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineAgent.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TimelineAgent = function() {
+    // Not implemented.
+}
+
+// Must be kept in sync with TimelineItem.h
+WebInspector.TimelineAgent.RecordType = {
+    EventDispatch : 0,
+    Layout : 1,
+    RecalculateStyles : 2,
+    Paint : 3,
+    ParseHTML : 4,
+    TimerInstall : 5,
+    TimerRemove : 6,
+    TimerFire : 7,
+    XHRReadyStateChange : 8,
+    XHRLoad : 9,
+    EvaluateScript : 10,
+    MarkTimeline : 11,
+    ResourceSendRequest : 12,
+    ResourceReceiveResponse : 13,
+    ResourceFinish : 14,
+    FunctionCall : 15,
+    ResourceReceiveData: 16,
+    GCEvent : 17,
+    MarkDOMContentEventType : 18,
+    MarkLoadEventType : 19,
+    ScheduleResourceRequest : 20
+};
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineGrid.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineGrid.js
new file mode 100644
index 0000000..adc8e47
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineGrid.js
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TimelineGrid = function()
+{
+    this.element = document.createElement("div");
+
+    this._itemsGraphsElement = document.createElement("div");
+    this._itemsGraphsElement.id = "resources-graphs";
+    this.element.appendChild(this._itemsGraphsElement);
+
+    this._dividersElement = document.createElement("div");
+    this._dividersElement.className = "resources-dividers";
+    this.element.appendChild(this._dividersElement);
+
+    this._eventDividersElement = document.createElement("div");
+    this._eventDividersElement.className = "resources-event-dividers";
+    this.element.appendChild(this._eventDividersElement);
+
+    this._dividersLabelBarElement = document.createElement("div");
+    this._dividersLabelBarElement.className = "resources-dividers-label-bar";
+    this.element.appendChild(this._dividersLabelBarElement);
+}
+
+WebInspector.TimelineGrid.prototype = {
+    get itemsGraphsElement()
+    {
+        return this._itemsGraphsElement;
+    },
+
+    
+    updateDividers: function(force, calculator, paddingLeft)
+    {
+        var dividerCount = Math.round(this._dividersElement.offsetWidth / 64);
+        var slice = calculator.boundarySpan / dividerCount;
+        if (!force && this._currentDividerSlice === slice)
+            return false;
+
+        if (typeof paddingLeft !== "number")
+            paddingLeft = 0;
+        this._currentDividerSlice = slice;
+
+        // Reuse divider elements and labels.
+        var divider = this._dividersElement.firstChild;
+        var dividerLabelBar = this._dividersLabelBarElement.firstChild;
+
+        var dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth;
+        var clientWidth = dividersLabelBarElementClientWidth - paddingLeft;
+        for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) {
+            if (!divider) {
+                divider = document.createElement("div");
+                divider.className = "resources-divider";
+                this._dividersElement.appendChild(divider);
+
+                dividerLabelBar = document.createElement("div");
+                dividerLabelBar.className = "resources-divider";
+                var label = document.createElement("div");
+                label.className = "resources-divider-label";
+                dividerLabelBar._labelElement = label;
+                dividerLabelBar.appendChild(label);
+                this._dividersLabelBarElement.appendChild(dividerLabelBar);
+                dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth;
+            }
+
+            if (i === (paddingLeft ? 0 : 1)) {
+                divider.addStyleClass("first");
+                dividerLabelBar.addStyleClass("first");
+            } else {
+                divider.removeStyleClass("first");
+                dividerLabelBar.removeStyleClass("first");
+            }
+
+            if (i === dividerCount) {
+                divider.addStyleClass("last");
+                dividerLabelBar.addStyleClass("last");
+            } else {
+                divider.removeStyleClass("last");
+                dividerLabelBar.removeStyleClass("last");
+            }
+
+            var left = paddingLeft + clientWidth * (i / dividerCount);
+            var percentLeft = 100 * left / dividersLabelBarElementClientWidth;
+            this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft);
+
+            if (!isNaN(slice))
+                dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i);
+            else
+                dividerLabelBar._labelElement.textContent = "";
+
+            divider = divider.nextSibling;
+            dividerLabelBar = dividerLabelBar.nextSibling;
+        }
+
+        // Remove extras.
+        while (divider) {
+            var nextDivider = divider.nextSibling;
+            this._dividersElement.removeChild(divider);
+            divider = nextDivider;
+        }
+        while (dividerLabelBar) {
+            var nextDivider = dividerLabelBar.nextSibling;
+            this._dividersLabelBarElement.removeChild(dividerLabelBar);
+            dividerLabelBar = nextDivider;
+        }
+        return true;
+    },
+
+    _setDividerAndBarLeft: function(divider, dividerLabelBar, percentLeft)
+    {
+        var percentStyleLeft = parseFloat(divider.style.left);
+        if (!isNaN(percentStyleLeft) && Math.abs(percentStyleLeft - percentLeft) < 0.1)
+            return;
+        divider.style.left = percentLeft + "%";
+        dividerLabelBar.style.left = percentLeft + "%";
+    },
+
+    addEventDivider: function(divider)
+    {
+        this._eventDividersElement.appendChild(divider);
+    },
+
+    addEventDividers: function(dividers)
+    {
+        this.element.removeChild(this._eventDividersElement);
+        for (var i = 0; i < dividers.length; ++i)
+            if (dividers[i])
+                this._eventDividersElement.appendChild(dividers[i]);
+        this.element.appendChild(this._eventDividersElement);
+    },
+
+    removeEventDividers: function()
+    {
+        this._eventDividersElement.removeChildren();
+    },
+
+    hideEventDividers: function()
+    {
+        this._eventDividersElement.addStyleClass("hidden");
+    },
+
+    showEventDividers: function()
+    {
+        this._eventDividersElement.removeStyleClass("hidden");
+    },
+
+    setScrollAndDividerTop: function(scrollTop, dividersTop)
+    {
+        this._dividersElement.style.top = scrollTop + "px";
+        this._eventDividersElement.style.top = scrollTop + "px";
+        this._dividersLabelBarElement.style.top = dividersTop + "px";
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineOverviewPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineOverviewPane.js
new file mode 100644
index 0000000..0dac916
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelineOverviewPane.js
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TimelineOverviewPane = function(categories)
+{
+    this._categories = categories;
+
+    this.statusBarFilters = document.createElement("div");
+    this.statusBarFilters.className = "status-bar-items";
+    for (var categoryName in this._categories) {
+        var category = this._categories[categoryName];
+        this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCheckboxClicked.bind(this, category)));
+    }
+
+    this._overviewGrid = new WebInspector.TimelineGrid();
+    this._overviewGrid.element.id = "timeline-overview-grid";
+    this._overviewGrid.itemsGraphsElement.id = "timeline-overview-timelines";
+    this._overviewGrid.element.addEventListener("mousedown", this._dragWindow.bind(this), true);
+
+    this._heapGraph = new WebInspector.HeapGraph();
+    this._heapGraph.element.id = "timeline-overview-memory";
+    this._overviewGrid.element.insertBefore(this._heapGraph.element, this._overviewGrid.itemsGraphsElement);
+
+    this.element = this._overviewGrid.element;
+
+    this._categoryGraphs = {};
+    var i = 0;
+    for (var category in this._categories) {
+        var categoryGraph = new WebInspector.TimelineCategoryGraph(this._categories[category], i++ % 2);
+        this._categoryGraphs[category] = categoryGraph;
+        this._overviewGrid.itemsGraphsElement.appendChild(categoryGraph.graphElement);
+    }
+    this._overviewGrid.setScrollAndDividerTop(0, 0);
+
+    this._overviewWindowElement = document.createElement("div");
+    this._overviewWindowElement.id = "timeline-overview-window";
+    this._overviewGrid.element.appendChild(this._overviewWindowElement);
+
+    this._overviewWindowBordersElement = document.createElement("div");
+    this._overviewWindowBordersElement.className = "timeline-overview-window-rulers";
+    this._overviewGrid.element.appendChild(this._overviewWindowBordersElement);
+
+    var overviewDividersBackground = document.createElement("div");
+    overviewDividersBackground.className = "timeline-overview-dividers-background";
+    this._overviewGrid.element.appendChild(overviewDividersBackground);
+
+    this._leftResizeElement = document.createElement("div");
+    this._leftResizeElement.className = "timeline-window-resizer";
+    this._leftResizeElement.style.left = 0;
+    this._overviewGrid.element.appendChild(this._leftResizeElement);
+
+    this._rightResizeElement = document.createElement("div");
+    this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right";
+    this._rightResizeElement.style.right = 0;
+    this._overviewGrid.element.appendChild(this._rightResizeElement);
+
+    this._overviewCalculator = new WebInspector.TimelineOverviewCalculator();
+
+    this.windowLeft = 0.0;
+    this.windowRight = 1.0;
+}
+
+WebInspector.TimelineOverviewPane.minSelectableSize = 12;
+
+WebInspector.TimelineOverviewPane.prototype = {
+    showTimelines: function(event) {
+        this._heapGraph.hide();
+        this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden");
+    },
+
+    showMemoryGraph: function(records) {
+        this._heapGraph.show();
+        this._heapGraph.update(records);
+        this._overviewGrid.itemsGraphsElement.addStyleClass("hidden");
+    },
+
+    _onCheckboxClicked: function (category, event) {
+        if (event.target.checked)
+            category.hidden = false;
+        else
+            category.hidden = true;
+        this._categoryGraphs[category.name].dimmed = !event.target.checked;
+        this.dispatchEventToListeners("filter changed");
+    },
+
+    _forAllRecords: function(recordsArray, callback)
+    {
+        if (!recordsArray)
+            return;
+        for (var i = 0; i < recordsArray.length; ++i) {
+            callback(recordsArray[i]);
+            this._forAllRecords(recordsArray[i].children, callback);
+        }
+    },
+
+    update: function(records, showShortEvents)
+    {
+        this._showShortEvents = showShortEvents;
+        // Clear summary bars.
+        var timelines = {};
+        for (var category in this._categories) {
+            timelines[category] = [];
+            this._categoryGraphs[category].clearChunks();
+        }
+
+        // Create sparse arrays with 101 cells each to fill with chunks for a given category.
+        this._overviewCalculator.reset();
+        this._forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator));
+
+        function markTimeline(record)
+        {
+            if (!(this._showShortEvents || record.isLong()))
+                return;
+            var percentages = this._overviewCalculator.computeBarGraphPercentages(record);
+
+            var end = Math.round(percentages.end);
+            var categoryName = record.category.name;
+            for (var j = Math.round(percentages.start); j <= end; ++j)
+                timelines[categoryName][j] = true;
+        }
+        this._forAllRecords(records, markTimeline.bind(this));
+
+        // Convert sparse arrays to continuous segments, render graphs for each.
+        for (var category in this._categories) {
+            var timeline = timelines[category];
+            window.timelineSaved = timeline;
+            var chunkStart = -1;
+            for (var j = 0; j < 101; ++j) {
+                if (timeline[j]) {
+                    if (chunkStart === -1)
+                        chunkStart = j;
+                } else {
+                    if (chunkStart !== -1) {
+                        this._categoryGraphs[category].addChunk(chunkStart, j);
+                        chunkStart = -1;
+                    }
+                }
+            }
+            if (chunkStart !== -1) {
+                this._categoryGraphs[category].addChunk(chunkStart, 100);
+                chunkStart = -1;
+            }
+        }
+
+        this._heapGraph.setSize(this._overviewGrid.element.offsetWidth, 60);
+        if (this._heapGraph.visible)
+            this._heapGraph.update(records);
+
+        this._overviewGrid.updateDividers(true, this._overviewCalculator);
+    },
+
+    updateEventDividers: function(records, dividerConstructor)
+    {
+        this._overviewGrid.removeEventDividers();
+        var dividers = [];
+        for (var i = 0; i < records.length; ++i) {
+            var record = records[i];
+            var positions = this._overviewCalculator.computeBarGraphPercentages(record);
+            var dividerPosition = Math.round(positions.start * 10);
+            if (dividers[dividerPosition])
+                continue;
+            var divider = dividerConstructor(record);
+            divider.style.left = positions.start + "%";
+            dividers[dividerPosition] = divider;
+        }
+        this._overviewGrid.addEventDividers(dividers);
+    },
+
+    updateMainViewWidth: function(width, records)
+    {
+        this._overviewGrid.element.style.left = width + "px";
+        this.statusBarFilters.style.left = Math.max(155, width) + "px";
+    },
+
+    reset: function()
+    {
+        this.windowLeft = 0.0;
+        this.windowRight = 1.0;
+        this._overviewWindowElement.style.left = "0%";
+        this._overviewWindowElement.style.width = "100%";
+        this._overviewWindowBordersElement.style.left = "0%";
+        this._overviewWindowBordersElement.style.right = "0%";
+        this._leftResizeElement.style.left = "0%";
+        this._rightResizeElement.style.left = "100%";
+        this._overviewCalculator.reset();
+        this._overviewGrid.updateDividers(true, this._overviewCalculator);
+    },
+
+    _resizeWindow: function(resizeElement, event)
+    {
+        WebInspector.elementDragStart(resizeElement, this._windowResizeDragging.bind(this, resizeElement), this._endWindowDragging.bind(this), event, "col-resize");
+    },
+
+    _windowResizeDragging: function(resizeElement, event)
+    {
+        if (resizeElement === this._leftResizeElement)
+            this._resizeWindowLeft(event.pageX - this._overviewGrid.element.offsetLeft);
+        else
+            this._resizeWindowRight(event.pageX - this._overviewGrid.element.offsetLeft);
+        event.preventDefault();
+    },
+
+    _dragWindow: function(event)
+    {
+        var node = event.target;
+        while (node) {
+            if (node === this._overviewGrid._dividersLabelBarElement) {
+                WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX,
+                    this._leftResizeElement.offsetLeft, this._rightResizeElement.offsetLeft), this._endWindowDragging.bind(this), event, "ew-resize");
+                break;
+            } else if (node === this._overviewGrid.element) {
+                var position = event.pageX - this._overviewGrid.element.offsetLeft;
+                this._overviewWindowSelector = new WebInspector.TimelinePanel.WindowSelector(this._overviewGrid.element, position, event);
+                WebInspector.elementDragStart(null, this._windowSelectorDragging.bind(this), this._endWindowSelectorDragging.bind(this), event, "col-resize");
+                break;
+            } else if (node === this._leftResizeElement || node === this._rightResizeElement) {
+                this._resizeWindow(node, event);
+                break;
+            }
+            node = node.parentNode;
+        }
+    },
+
+    _windowSelectorDragging: function(event)
+    {
+        this._overviewWindowSelector._updatePosition(event.pageX - this._overviewGrid.element.offsetLeft);
+        event.preventDefault();
+    },
+
+    _endWindowSelectorDragging: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+        var window = this._overviewWindowSelector._close(event.pageX - this._overviewGrid.element.offsetLeft);
+        delete this._overviewWindowSelector;
+        if (window.end - window.start < WebInspector.TimelineOverviewPane.minSelectableSize)
+            if (this._overviewGrid.itemsGraphsElement.offsetWidth - window.end > WebInspector.TimelineOverviewPane.minSelectableSize)
+                window.end = window.start + WebInspector.TimelineOverviewPane.minSelectableSize;
+            else
+                window.start = window.end - WebInspector.TimelineOverviewPane.minSelectableSize;
+        this._setWindowPosition(window.start, window.end);
+    },
+
+    _windowDragging: function(startX, windowLeft, windowRight, event)
+    {
+        var delta = event.pageX - startX;
+        var start = windowLeft + delta;
+        var end = windowRight + delta;
+        var windowSize = windowRight - windowLeft;
+
+        if (start < 0) {
+            start = 0;
+            end = windowSize;
+        }
+
+        if (end > this._overviewGrid.element.clientWidth) {
+            end = this._overviewGrid.element.clientWidth;
+            start = end - windowSize;
+        }
+        this._setWindowPosition(start, end);
+
+        event.preventDefault();
+    },
+
+    _resizeWindowLeft: function(start)
+    {
+        // Glue to edge.
+        if (start < 10)
+            start = 0;
+        else if (start > this._rightResizeElement.offsetLeft -  4)
+            start = this._rightResizeElement.offsetLeft - 4;
+        this._setWindowPosition(start, null);
+    },
+
+    _resizeWindowRight: function(end)
+    {
+        // Glue to edge.
+        if (end > this._overviewGrid.element.clientWidth - 10)
+            end = this._overviewGrid.element.clientWidth;
+        else if (end < this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize)
+            end = this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize;
+        this._setWindowPosition(null, end);
+    },
+
+    _setWindowPosition: function(start, end)
+    {
+        const rulerAdjustment = 1 / this._overviewGrid.element.clientWidth;
+        if (typeof start === "number") {
+            this.windowLeft = start / this._overviewGrid.element.clientWidth;
+            this._leftResizeElement.style.left = this.windowLeft * 100 + "%";
+            this._overviewWindowElement.style.left = this.windowLeft * 100 + "%";
+            this._overviewWindowBordersElement.style.left = (this.windowLeft - rulerAdjustment) * 100 + "%";
+        }
+        if (typeof end === "number") {
+            this.windowRight = end / this._overviewGrid.element.clientWidth;
+            this._rightResizeElement.style.left = this.windowRight * 100 + "%";
+        }
+        this._overviewWindowElement.style.width = (this.windowRight - this.windowLeft) * 100 + "%";
+        this._overviewWindowBordersElement.style.right = (1 - this.windowRight + 2 * rulerAdjustment) * 100 + "%";
+        this.dispatchEventToListeners("window changed");
+    },
+
+    _endWindowDragging: function(event)
+    {
+        WebInspector.elementDragEnd(event);
+    },
+
+    _createTimelineCategoryStatusBarCheckbox: function(category, onCheckboxClicked)
+    {
+        var labelContainer = document.createElement("div");
+        labelContainer.addStyleClass("timeline-category-statusbar-item");
+        labelContainer.addStyleClass("timeline-category-" + category.name);
+        labelContainer.addStyleClass("status-bar-item");
+
+        var label = document.createElement("label");
+        var checkElement = document.createElement("input");
+        checkElement.type = "checkbox";
+        checkElement.className = "timeline-category-checkbox";
+        checkElement.checked = true;
+        checkElement.addEventListener("click", onCheckboxClicked);
+        label.appendChild(checkElement);
+
+        var typeElement = document.createElement("span");
+        typeElement.className = "type";
+        typeElement.textContent = category.title;
+        label.appendChild(typeElement);
+
+        labelContainer.appendChild(label);
+        return labelContainer;
+    }
+
+}
+
+WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.Object.prototype;
+
+
+WebInspector.TimelineOverviewCalculator = function()
+{
+}
+
+WebInspector.TimelineOverviewCalculator.prototype = {
+    computeBarGraphPercentages: function(record)
+    {
+        var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100;
+        var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100;
+        return {start: start, end: end};
+    },
+
+    reset: function()
+    {
+        delete this.minimumBoundary;
+        delete this.maximumBoundary;
+    },
+
+    updateBoundaries: function(record)
+    {
+        if (typeof this.minimumBoundary === "undefined" || record.startTime < this.minimumBoundary) {
+            this.minimumBoundary = record.startTime;
+            return true;
+        }
+        if (typeof this.maximumBoundary === "undefined" || record.endTime > this.maximumBoundary) {
+            this.maximumBoundary = record.endTime;
+            return true;
+        }
+        return false;
+    },
+
+    get boundarySpan()
+    {
+        return this.maximumBoundary - this.minimumBoundary;
+    },
+
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value);
+    }
+}
+
+
+WebInspector.TimelineCategoryGraph = function(category, isEven)
+{
+    this._category = category;
+
+    this._graphElement = document.createElement("div");
+    this._graphElement.className = "timeline-graph-side timeline-overview-graph-side" + (isEven ? " even" : "");
+
+    this._barAreaElement = document.createElement("div");
+    this._barAreaElement.className = "timeline-graph-bar-area timeline-category-" + category.name;
+    this._graphElement.appendChild(this._barAreaElement);
+}
+
+WebInspector.TimelineCategoryGraph.prototype = {
+    get graphElement()
+    {
+        return this._graphElement;
+    },
+
+    addChunk: function(start, end)
+    {
+        var chunk = document.createElement("div");
+        chunk.className = "timeline-graph-bar";
+        this._barAreaElement.appendChild(chunk);
+        chunk.style.setProperty("left", start + "%");
+        chunk.style.setProperty("width", (end - start) + "%");
+    },
+
+    clearChunks: function()
+    {
+        this._barAreaElement.removeChildren();
+    },
+
+    set dimmed(dimmed)
+    {
+        if (dimmed)
+            this._barAreaElement.removeStyleClass("timeline-category-" + this._category.name);
+        else
+            this._barAreaElement.addStyleClass("timeline-category-" + this._category.name);
+    }
+}
+
+WebInspector.TimelinePanel.WindowSelector = function(parent, position, event)
+{
+    this._startPosition = position;
+    this._width = parent.offsetWidth;
+    this._windowSelector = document.createElement("div");
+    this._windowSelector.className = "timeline-window-selector";
+    this._windowSelector.style.left = this._startPosition + "px";
+    this._windowSelector.style.right = this._width - this._startPosition +  + "px";
+    parent.appendChild(this._windowSelector);
+}
+
+WebInspector.TimelinePanel.WindowSelector.prototype = {
+    _createSelectorElement: function(parent, left, width, height)
+    {
+        var selectorElement = document.createElement("div");
+        selectorElement.className = "timeline-window-selector";
+        selectorElement.style.left = left + "px";
+        selectorElement.style.width = width + "px";
+        selectorElement.style.top = "0px";
+        selectorElement.style.height = height + "px";
+        parent.appendChild(selectorElement);
+        return selectorElement;
+    },
+
+    _close: function(position)
+    {
+        position = Math.max(0, Math.min(position, this._width));
+        this._windowSelector.parentNode.removeChild(this._windowSelector);
+        return this._startPosition < position ? {start: this._startPosition, end: position} : {start: position, end: this._startPosition};
+    },
+
+    _updatePosition: function(position)
+    {
+        position = Math.max(0, Math.min(position, this._width));
+        if (position < this._startPosition) {
+            this._windowSelector.style.left = position + "px";
+            this._windowSelector.style.right = this._width - this._startPosition + "px";
+        } else {
+            this._windowSelector.style.left = this._startPosition + "px";
+            this._windowSelector.style.right = this._width - position + "px";
+        }
+    }
+}
+
+WebInspector.HeapGraph = function() {
+    this._canvas = document.createElement("canvas");
+
+    this._maxHeapSizeLabel = document.createElement("div");
+    this._maxHeapSizeLabel.addStyleClass("memory-graph-label");
+
+    this._element = document.createElement("div");
+    this._element.addStyleClass("hidden");
+    this._element.appendChild(this._canvas);
+    this._element.appendChild(this._maxHeapSizeLabel);
+}
+
+WebInspector.HeapGraph.prototype = {
+    get element() {
+    //    return this._canvas;
+        return this._element;
+    },
+
+    get visible() {
+        return !this.element.hasStyleClass("hidden");
+    },
+
+    show: function() {
+        this.element.removeStyleClass("hidden");
+    },
+
+    hide: function() {
+        this.element.addStyleClass("hidden");
+    },
+
+    setSize: function(w, h) {
+        this._canvas.width = w;
+        this._canvas.height = h - 5;
+    },
+
+    update: function(records)
+    {
+        if (!records.length)
+            return;
+
+        var maxTotalHeapSize = 0;
+        var minTime;
+        var maxTime;
+        this._forAllRecords(records, function(r) {
+            if (r.totalHeapSize && r.totalHeapSize > maxTotalHeapSize)
+                maxTotalHeapSize = r.totalHeapSize;
+
+            if (typeof minTime === "undefined" || r.startTime < minTime)
+                minTime = r.startTime;
+            if (typeof maxTime === "undefined" || r.endTime > maxTime)
+                maxTime = r.endTime;
+        });
+
+        var width = this._canvas.width;
+        var height = this._canvas.height;
+        var xFactor = width / (maxTime - minTime);
+        var yFactor = height / maxTotalHeapSize;
+
+        var histogram = new Array(width);
+        this._forAllRecords(records, function(r) {
+            if (!r.usedHeapSize)
+                return;
+             var x = Math.round((r.endTime - minTime) * xFactor);
+             var y = Math.round(r.usedHeapSize * yFactor);
+             histogram[x] = Math.max(histogram[x] || 0, y);
+        });
+
+        var ctx = this._canvas.getContext("2d");
+        this._clear(ctx);
+
+        // +1 so that the border always fit into the canvas area.
+        height = height + 1;
+
+        ctx.beginPath();
+        var initialY = 0;
+        for (var k = 0; k < histogram.length; k++) {
+            if (histogram[k]) {
+                initialY = histogram[k];
+                break;
+            }
+        }
+        ctx.moveTo(0, height - initialY);
+
+        for (var x = 0; x < histogram.length; x++) {
+             if (!histogram[x])
+                 continue;
+             ctx.lineTo(x, height - histogram[x]);
+        }
+
+        ctx.lineWidth = 0.5;
+        ctx.strokeStyle = "rgba(20,0,0,0.8)";
+        ctx.stroke();
+
+        ctx.fillStyle = "rgba(214,225,254, 0.8);";
+        ctx.lineTo(width, 60);
+        ctx.lineTo(0, 60);
+        ctx.lineTo(0, height - initialY);
+        ctx.fill();
+        ctx.closePath();
+
+        this._maxHeapSizeLabel.textContent = Number.bytesToString(maxTotalHeapSize);
+    },
+
+    _clear: function(ctx) {
+        ctx.fillStyle = "rgba(255,255,255,0.8)";
+        ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
+    },
+
+    _forAllRecords: WebInspector.TimelineOverviewPane.prototype._forAllRecords
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelinePanel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelinePanel.js
new file mode 100644
index 0000000..1d8b9c9
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TimelinePanel.js
@@ -0,0 +1,1178 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TimelinePanel = function()
+{
+    WebInspector.Panel.call(this, "timeline");
+
+    this.element.appendChild(this._createTopPane());
+    this.element.tabIndex = 0;
+
+    this._sidebarBackgroundElement = document.createElement("div");
+    this._sidebarBackgroundElement.className = "sidebar timeline-sidebar-background";
+    this.element.appendChild(this._sidebarBackgroundElement);
+
+    this._containerElement = document.createElement("div");
+    this._containerElement.id = "timeline-container";
+    this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false);
+    this.element.appendChild(this._containerElement);
+
+    this.createSidebar(this._containerElement, this._containerElement);
+    var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true);
+    itemsTreeElement.expanded = true;
+    this.sidebarTree.appendChild(itemsTreeElement);
+
+    this._sidebarListElement = document.createElement("div");
+    this.sidebarElement.appendChild(this._sidebarListElement);
+
+    this._containerContentElement = document.createElement("div");
+    this._containerContentElement.id = "resources-container-content";
+    this._containerElement.appendChild(this._containerContentElement);
+
+    this._timelineGrid = new WebInspector.TimelineGrid();
+    this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement;
+    this._itemsGraphsElement.id = "timeline-graphs";
+    this._containerContentElement.appendChild(this._timelineGrid.element);
+
+    this._topGapElement = document.createElement("div");
+    this._topGapElement.className = "timeline-gap";
+    this._itemsGraphsElement.appendChild(this._topGapElement);
+
+    this._graphRowsElement = document.createElement("div");
+    this._itemsGraphsElement.appendChild(this._graphRowsElement);
+
+    this._bottomGapElement = document.createElement("div");
+    this._bottomGapElement.className = "timeline-gap";
+    this._itemsGraphsElement.appendChild(this._bottomGapElement);
+
+    this._expandElements = document.createElement("div");
+    this._expandElements.id = "orphan-expand-elements";
+    this._itemsGraphsElement.appendChild(this._expandElements);
+
+    this._rootRecord = this._createRootRecord();
+    this._sendRequestRecords = {};
+    this._scheduledResourceRequests = {};
+    this._timerRecords = {};
+
+    this._calculator = new WebInspector.TimelineCalculator();
+    this._calculator._showShortEvents = false;
+    var shortRecordThresholdTitle = Number.secondsToString(WebInspector.TimelinePanel.shortRecordThreshold);
+    this._showShortRecordsTitleText = WebInspector.UIString("Show the records that are shorter than %s", shortRecordThresholdTitle);
+    this._hideShortRecordsTitleText = WebInspector.UIString("Hide the records that are shorter than %s", shortRecordThresholdTitle);
+    this._createStatusbarButtons();
+
+    this._boundariesAreValid = true;
+    this._scrollTop = 0;
+
+    this._popoverHelper = new WebInspector.PopoverHelper(this._containerElement, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);
+
+    // Disable short events filter by default.
+    this.toggleFilterButton.toggled = true;
+    this._calculator._showShortEvents = this.toggleFilterButton.toggled;
+    this._markTimelineRecords = [];
+    this._expandOffset = 15;
+
+    InspectorBackend.registerDomainDispatcher("Timeline", new WebInspector.TimelineDispatcher(this));
+}
+
+// Define row height, should be in sync with styles for timeline graphs.
+WebInspector.TimelinePanel.rowHeight = 18;
+WebInspector.TimelinePanel.shortRecordThreshold = 0.015;
+
+WebInspector.TimelinePanel.prototype = {
+    _createTopPane: function() {
+        var topPaneElement = document.createElement("div");
+        topPaneElement.id = "timeline-overview-panel";
+
+        this._topPaneSidebarElement = document.createElement("div");
+        this._topPaneSidebarElement.id = "timeline-overview-sidebar";
+
+        var overviewTreeElement = document.createElement("ol");
+        overviewTreeElement.className = "sidebar-tree";
+        this._topPaneSidebarElement.appendChild(overviewTreeElement);
+        topPaneElement.appendChild(this._topPaneSidebarElement);
+
+        var topPaneSidebarTree = new TreeOutline(overviewTreeElement);
+        var timelinesOverviewItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Timelines"));
+        topPaneSidebarTree.appendChild(timelinesOverviewItem);
+        timelinesOverviewItem.onselect = this._timelinesOverviewItemSelected.bind(this);
+        timelinesOverviewItem.select(true);
+
+        var memoryOverviewItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Memory"));
+        topPaneSidebarTree.appendChild(memoryOverviewItem);
+        memoryOverviewItem.onselect = this._memoryOverviewItemSelected.bind(this);
+
+        this._overviewPane = new WebInspector.TimelineOverviewPane(this.categories);
+        this._overviewPane.addEventListener("window changed", this._windowChanged, this);
+        this._overviewPane.addEventListener("filter changed", this._refresh, this);
+        topPaneElement.appendChild(this._overviewPane.element);
+
+        var separatorElement = document.createElement("div");
+        separatorElement.id = "timeline-overview-separator";
+        topPaneElement.appendChild(separatorElement);
+        return topPaneElement;
+    },
+
+    get toolbarItemLabel()
+    {
+        return WebInspector.UIString("Timeline");
+    },
+
+    get statusBarItems()
+    {
+        return [this.toggleFilterButton.element, this.toggleTimelineButton.element, this.clearButton.element, this._overviewPane.statusBarFilters];
+    },
+
+    get categories()
+    {
+        if (!this._categories) {
+            this._categories = {
+                loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), "rgb(47,102,236)"),
+                scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), "rgb(157,231,119)"),
+                rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)")
+            };
+        }
+        return this._categories;
+    },
+
+    get defaultFocusedElement()
+    {
+        return this.element;
+    },
+
+    get _recordStyles()
+    {
+        if (!this._recordStylesArray) {
+            var recordTypes = WebInspector.TimelineAgent.RecordType;
+            var recordStyles = {};
+            recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: this.categories.scripting };
+            recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: this.categories.rendering };
+            recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: this.categories.rendering };
+            recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: this.categories.rendering };
+            recordStyles[recordTypes.ParseHTML] = { title: WebInspector.UIString("Parse"), category: this.categories.loading };
+            recordStyles[recordTypes.TimerInstall] = { title: WebInspector.UIString("Install Timer"), category: this.categories.scripting };
+            recordStyles[recordTypes.TimerRemove] = { title: WebInspector.UIString("Remove Timer"), category: this.categories.scripting };
+            recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: this.categories.scripting };
+            recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: this.categories.scripting };
+            recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: this.categories.scripting };
+            recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting };
+            recordStyles[recordTypes.MarkTimeline] = { title: WebInspector.UIString("Mark"), category: this.categories.scripting };
+            recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: this.categories.loading };
+            recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: this.categories.loading };
+            recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: this.categories.loading };
+            recordStyles[recordTypes.FunctionCall] = { title: WebInspector.UIString("Function Call"), category: this.categories.scripting };
+            recordStyles[recordTypes.ResourceReceiveData] = { title: WebInspector.UIString("Receive Data"), category: this.categories.loading };
+            recordStyles[recordTypes.GCEvent] = { title: WebInspector.UIString("GC Event"), category: this.categories.scripting };
+            recordStyles[recordTypes.MarkDOMContentEventType] = { title: WebInspector.UIString("DOMContent event"), category: this.categories.scripting };
+            recordStyles[recordTypes.MarkLoadEventType] = { title: WebInspector.UIString("Load event"), category: this.categories.scripting };
+            recordStyles[recordTypes.ScheduleResourceRequest] = { title: WebInspector.UIString("Schedule Request"), category: this.categories.loading };
+            this._recordStylesArray = recordStyles;
+        }
+        return this._recordStylesArray;
+    },
+
+    _createStatusbarButtons: function()
+    {
+        this.toggleTimelineButton = new WebInspector.StatusBarButton(WebInspector.UIString("Record"), "record-profile-status-bar-item");
+        this.toggleTimelineButton.addEventListener("click", this._toggleTimelineButtonClicked.bind(this), false);
+
+        this.clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
+        this.clearButton.addEventListener("click", this._clearPanel.bind(this), false);
+
+        this.toggleFilterButton = new WebInspector.StatusBarButton(this._hideShortRecordsTitleText, "timeline-filter-status-bar-item");
+        this.toggleFilterButton.addEventListener("click", this._toggleFilterButtonClicked.bind(this), false);
+
+        this.recordsCounter = document.createElement("span");
+        this.recordsCounter.className = "timeline-records-counter";
+    },
+
+    _updateRecordsCounter: function()
+    {
+        this.recordsCounter.textContent = WebInspector.UIString("%d of %d captured records are visible", this._rootRecord._visibleRecordsCount, this._rootRecord._allRecordsCount);
+    },
+
+    _updateEventDividers: function()
+    {
+        this._timelineGrid.removeEventDividers();
+        var clientWidth = this._graphRowsElement.offsetWidth - this._expandOffset;
+        var dividers = [];
+        for (var i = 0; i < this._markTimelineRecords.length; ++i) {
+            var record = this._markTimelineRecords[i];
+            var positions = this._calculator.computeBarGraphWindowPosition(record, clientWidth);
+            var dividerPosition = Math.round(positions.left);
+            if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers[dividerPosition])
+                continue;
+            var divider = this._createEventDivider(record);
+            divider.style.left = (dividerPosition + this._expandOffset) + "px";
+            dividers[dividerPosition] = divider;
+        }
+        this._timelineGrid.addEventDividers(dividers);
+        this._overviewPane.updateEventDividers(this._markTimelineRecords, this._createEventDivider.bind(this));
+    },
+
+    _createEventDivider: function(record)
+    {
+        var eventDivider = document.createElement("div");
+        eventDivider.className = "resources-event-divider";
+        var recordTypes = WebInspector.TimelineAgent.RecordType;
+
+        var eventDividerPadding = document.createElement("div");
+        eventDividerPadding.className = "resources-event-divider-padding";
+        eventDividerPadding.title = record.title;
+
+        if (record.type === recordTypes.MarkDOMContentEventType)
+            eventDivider.className += " resources-blue-divider";
+        else if (record.type === recordTypes.MarkLoadEventType)
+            eventDivider.className += " resources-red-divider";
+        else if (record.type === recordTypes.MarkTimeline) {
+            eventDivider.className += " resources-orange-divider";
+            eventDividerPadding.title = record.data.message;
+        }
+        eventDividerPadding.appendChild(eventDivider);
+        return eventDividerPadding;
+    },
+
+    _timelinesOverviewItemSelected: function(event) {
+        this._overviewPane.showTimelines();
+    },
+
+    _memoryOverviewItemSelected: function(event) {
+        this._overviewPane.showMemoryGraph(this._rootRecord.children);
+    },
+
+    _toggleTimelineButtonClicked: function()
+    {
+        if (this.toggleTimelineButton.toggled)
+            InspectorBackend.stopTimelineProfiler();
+        else {
+            this._clearPanel();
+            InspectorBackend.startTimelineProfiler();
+        }
+    },
+
+    _toggleFilterButtonClicked: function()
+    {
+        this.toggleFilterButton.toggled = !this.toggleFilterButton.toggled;
+        this._calculator._showShortEvents = this.toggleFilterButton.toggled;
+        this.toggleFilterButton.element.title = this._calculator._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText;
+        this._scheduleRefresh(true);
+    },
+
+    _timelineProfilerWasStarted: function()
+    {
+        this.toggleTimelineButton.toggled = true;
+    },
+
+    _timelineProfilerWasStopped: function()
+    {
+        this.toggleTimelineButton.toggled = false;
+    },
+
+    _addRecordToTimeline: function(record)
+    {
+        if (record.type == WebInspector.TimelineAgent.RecordType.ResourceSendRequest) {
+            var isMainResource = (record.data.identifier === WebInspector.mainResource.identifier);
+            if (isMainResource && this._mainResourceIdentifier !== record.data.identifier) {
+                // We are loading new main resource -> clear the panel. Check above is necessary since
+                // there may be several resource loads with main resource marker upon redirects, redirects are reported with
+                // the original identifier.
+                this._mainResourceIdentifier = record.data.identifier;
+                this._clearPanel();
+            }
+        }
+        this._innerAddRecordToTimeline(record, this._rootRecord);
+        this._scheduleRefresh();
+    },
+
+    _findParentRecord: function(record)
+    {
+        var recordTypes = WebInspector.TimelineAgent.RecordType;
+        var parentRecord;
+        if (record.type === recordTypes.ResourceReceiveResponse ||
+            record.type === recordTypes.ResourceFinish ||
+            record.type === recordTypes.ResourceReceiveData)
+            parentRecord = this._sendRequestRecords[record.data.identifier];
+        else if (record.type === recordTypes.TimerFire)
+            parentRecord = this._timerRecords[record.data.timerId];
+        else if (record.type === recordTypes.ResourceSendRequest)
+            parentRecord = this._scheduledResourceRequests[record.data.url];
+        return parentRecord;
+    },
+
+    _innerAddRecordToTimeline: function(record, parentRecord)
+    {
+        var connectedToOldRecord = false;
+        var recordTypes = WebInspector.TimelineAgent.RecordType;
+        if (record.type === recordTypes.MarkDOMContentEventType || record.type === recordTypes.MarkLoadEventType)
+            parentRecord = null; // No bar entry for load events.
+        else if (parentRecord === this._rootRecord) {
+            var newParentRecord = this._findParentRecord(record);
+            if (newParentRecord) {
+                parentRecord = newParentRecord;
+                connectedToOldRecord = true;
+            }
+        }
+
+        if (record.type == recordTypes.TimerFire && record.children && record.children.length) {
+            var childRecord = record.children[0];
+            if (childRecord.type === recordTypes.FunctionCall) {
+                record.data.scriptName = childRecord.data.scriptName;
+                record.data.scriptLine = childRecord.data.scriptLine;
+                record.children.shift();
+                record.children = childRecord.children.concat(record.children);
+            }
+        }
+
+        var formattedRecord = new WebInspector.TimelinePanel.FormattedRecord(record, parentRecord, this);
+
+        if (record.type === recordTypes.MarkDOMContentEventType || record.type === recordTypes.MarkLoadEventType) {
+            this._markTimelineRecords.push(formattedRecord);
+            return;
+        }
+
+        ++this._rootRecord._allRecordsCount;
+        formattedRecord.collapsed = (parentRecord === this._rootRecord);
+
+        var childrenCount = record.children ? record.children.length : 0;
+        for (var i = 0; i < childrenCount; ++i)
+            this._innerAddRecordToTimeline(record.children[i], formattedRecord);
+
+        formattedRecord._calculateAggregatedStats(this.categories);
+
+        if (connectedToOldRecord) {
+            var record = formattedRecord;
+            do {
+                var parent = record.parent;
+                parent._cpuTime += formattedRecord._cpuTime;
+                if (parent._lastChildEndTime < record._lastChildEndTime)
+                    parent._lastChildEndTime = record._lastChildEndTime;
+                for (var category in formattedRecord._aggregatedStats)
+                    parent._aggregatedStats[category] += formattedRecord._aggregatedStats[category];
+                record = parent;
+            } while (record.parent);
+        } else
+            if (parentRecord !== this._rootRecord)
+                parentRecord._selfTime -= formattedRecord.endTime - formattedRecord.startTime;
+
+        // Keep bar entry for mark timeline since nesting might be interesting to the user.
+        if (record.type === recordTypes.MarkTimeline)
+            this._markTimelineRecords.push(formattedRecord);
+    },
+
+    setSidebarWidth: function(width)
+    {
+        WebInspector.Panel.prototype.setSidebarWidth.call(this, width);
+        this._sidebarBackgroundElement.style.width = width + "px";
+        this._topPaneSidebarElement.style.width = width + "px";
+    },
+
+    updateMainViewWidth: function(width)
+    {
+        this._containerContentElement.style.left = width + "px";
+        this._scheduleRefresh();
+        this._overviewPane.updateMainViewWidth(width);
+    },
+
+    resize: function()
+    {
+        this._closeRecordDetails();
+        this._scheduleRefresh();
+    },
+
+    _createRootRecord: function()
+    {
+        var rootRecord = {};
+        rootRecord.children = [];
+        rootRecord._visibleRecordsCount = 0;
+        rootRecord._allRecordsCount = 0;
+        rootRecord._aggregatedStats = {};
+        return rootRecord;
+    },
+
+    _clearPanel: function()
+    {
+        this._markTimelineRecords = [];
+        this._sendRequestRecords = {};
+        this._scheduledResourceRequests = {};
+        this._timerRecords = {};
+        this._rootRecord = this._createRootRecord();
+        this._boundariesAreValid = false;
+        this._overviewPane.reset();
+        this._adjustScrollPosition(0);
+        this._refresh();
+        this._closeRecordDetails();
+    },
+
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        if (typeof this._scrollTop === "number")
+            this._containerElement.scrollTop = this._scrollTop;
+        this._refresh();
+        WebInspector.drawer.currentPanelCounters = this.recordsCounter;
+    },
+
+    hide: function()
+    {
+        WebInspector.Panel.prototype.hide.call(this);
+        this._closeRecordDetails();
+        WebInspector.drawer.currentPanelCounters = null;
+    },
+
+    _onScroll: function(event)
+    {
+        this._closeRecordDetails();
+        var scrollTop = this._containerElement.scrollTop;
+        var dividersTop = Math.max(0, scrollTop);
+        this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop);
+        this._scheduleRefresh(true);
+    },
+
+    _windowChanged: function()
+    {
+        this._closeRecordDetails();
+        this._scheduleRefresh();
+    },
+
+    _scheduleRefresh: function(preserveBoundaries)
+    {
+        this._closeRecordDetails();
+        this._boundariesAreValid &= preserveBoundaries;
+
+        if (!this.visible)
+            return;
+
+        if (preserveBoundaries)
+            this._refresh();
+        else
+            if (!this._refreshTimeout)
+                this._refreshTimeout = setTimeout(this._refresh.bind(this), 100);
+    },
+
+    _refresh: function()
+    {
+        if (this._refreshTimeout) {
+            clearTimeout(this._refreshTimeout);
+            delete this._refreshTimeout;
+        }
+
+        this._overviewPane.update(this._rootRecord.children, this._calculator._showShortEvents);
+        this._refreshRecords(!this._boundariesAreValid);
+        this._updateRecordsCounter();
+        if(!this._boundariesAreValid)
+            this._updateEventDividers();
+        this._boundariesAreValid = true;
+    },
+
+    _updateBoundaries: function()
+    {
+        this._calculator.reset();
+        this._calculator.windowLeft = this._overviewPane.windowLeft;
+        this._calculator.windowRight = this._overviewPane.windowRight;
+
+        for (var i = 0; i < this._rootRecord.children.length; ++i)
+            this._calculator.updateBoundaries(this._rootRecord.children[i]);
+
+        this._calculator.calculateWindow();
+    },
+
+    _addToRecordsWindow: function(record, recordsWindow, parentIsCollapsed)
+    {
+        if (!this._calculator._showShortEvents && !record.isLong())
+            return;
+        var percentages = this._calculator.computeBarGraphPercentages(record);
+        if (percentages.start < 100 && percentages.endWithChildren >= 0 && !record.category.hidden) {
+            ++this._rootRecord._visibleRecordsCount;
+            ++record.parent._invisibleChildrenCount;
+            if (!parentIsCollapsed)
+                recordsWindow.push(record);
+        }
+
+        var index = recordsWindow.length;
+        record._invisibleChildrenCount = 0;
+        for (var i = 0; i < record.children.length; ++i)
+            this._addToRecordsWindow(record.children[i], recordsWindow, parentIsCollapsed || record.collapsed);
+        record._visibleChildrenCount = recordsWindow.length - index;
+    },
+
+    _filterRecords: function()
+    {
+        var recordsInWindow = [];
+        this._rootRecord._visibleRecordsCount = 0;
+        for (var i = 0; i < this._rootRecord.children.length; ++i)
+            this._addToRecordsWindow(this._rootRecord.children[i], recordsInWindow);
+        return recordsInWindow;
+    },
+
+    _refreshRecords: function(updateBoundaries)
+    {
+        if (updateBoundaries)
+            this._updateBoundaries();
+
+        var recordsInWindow = this._filterRecords();
+
+        // Calculate the visible area.
+        this._scrollTop = this._containerElement.scrollTop;
+        var visibleTop = this._scrollTop;
+        var visibleBottom = visibleTop + this._containerElement.clientHeight;
+
+        const rowHeight = WebInspector.TimelinePanel.rowHeight;
+
+        // Convert visible area to visible indexes. Always include top-level record for a visible nested record.
+        var startIndex = Math.max(0, Math.min(Math.floor(visibleTop / rowHeight) - 1, recordsInWindow.length - 1));
+        var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));
+
+        // Resize gaps first.
+        const top = (startIndex * rowHeight) + "px";
+        this._topGapElement.style.height = top;
+        this.sidebarElement.style.top = top;
+        this.sidebarResizeElement.style.top = top;
+        this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px";
+
+        // Update visible rows.
+        var listRowElement = this._sidebarListElement.firstChild;
+        var width = this._graphRowsElement.offsetWidth;
+        this._itemsGraphsElement.removeChild(this._graphRowsElement);
+        var graphRowElement = this._graphRowsElement.firstChild;
+        var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true);
+        this._itemsGraphsElement.removeChild(this._expandElements);
+        this._expandElements.removeChildren();
+
+        for (var i = 0; i < endIndex; ++i) {
+            var record = recordsInWindow[i];
+            var isEven = !(i % 2);
+
+            if (i < startIndex) {
+                var lastChildIndex = i + record._visibleChildrenCount;
+                if (lastChildIndex >= startIndex && lastChildIndex < endIndex) {
+                    var expandElement = new WebInspector.TimelineExpandableElement(this._expandElements);
+                    expandElement._update(record, i, this._calculator.computeBarGraphWindowPosition(record, width - this._expandOffset));
+                }
+            } else {
+                if (!listRowElement) {
+                    listRowElement = new WebInspector.TimelineRecordListRow().element;
+                    this._sidebarListElement.appendChild(listRowElement);
+                }
+                if (!graphRowElement) {
+                    graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element;
+                    this._graphRowsElement.appendChild(graphRowElement);
+                }
+
+                listRowElement.row.update(record, isEven, this._calculator, visibleTop);
+                graphRowElement.row.update(record, isEven, this._calculator, width, this._expandOffset, i);
+
+                listRowElement = listRowElement.nextSibling;
+                graphRowElement = graphRowElement.nextSibling;
+            }
+        }
+
+        // Remove extra rows.
+        while (listRowElement) {
+            var nextElement = listRowElement.nextSibling;
+            listRowElement.row.dispose();
+            listRowElement = nextElement;
+        }
+        while (graphRowElement) {
+            var nextElement = graphRowElement.nextSibling;
+            graphRowElement.row.dispose();
+            graphRowElement = nextElement;
+        }
+
+        this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement);
+        this._itemsGraphsElement.appendChild(this._expandElements);
+        this.sidebarResizeElement.style.height = this.sidebarElement.clientHeight + "px";
+        // Reserve some room for expand / collapse controls to the left for records that start at 0ms.
+        var timelinePaddingLeft = this._calculator.windowLeft === 0 ? this._expandOffset : 0;
+        if (updateBoundaries)
+            this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft);
+        this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight);
+    },
+
+    _adjustScrollPosition: function(totalHeight)
+    {
+        // Prevent the container from being scrolled off the end.
+        if ((this._containerElement.scrollTop + this._containerElement.offsetHeight) > totalHeight + 1)
+            this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight);
+    },
+
+    _getPopoverAnchor: function(element)
+    {
+        return element.enclosingNodeOrSelfWithClass("timeline-graph-bar") || element.enclosingNodeOrSelfWithClass("timeline-tree-item");
+    },
+
+    _showPopover: function(anchor)
+    {
+        var record = anchor.row._record;
+        var popover = new WebInspector.Popover(record._generatePopupContent(this._calculator, this.categories));
+        popover.show(anchor);
+        return popover;
+    },
+
+    _closeRecordDetails: function()
+    {
+        this._popoverHelper.hidePopup();
+    }
+}
+
+WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.TimelineDispatcher = function(timelinePanel)
+{
+    this._timelinePanel = timelinePanel;
+}
+
+WebInspector.TimelineDispatcher.prototype = {
+    timelineProfilerWasStarted: function()
+    {
+        this._timelinePanel._timelineProfilerWasStarted();
+    },
+
+    timelineProfilerWasStopped: function()
+    {
+        this._timelinePanel._timelineProfilerWasStopped();
+    },
+
+    addRecordToTimeline: function(record)
+    {
+        this._timelinePanel._addRecordToTimeline(record);
+    }
+}
+
+WebInspector.TimelineCategory = function(name, title, color)
+{
+    this.name = name;
+    this.title = title;
+    this.color = color;
+}
+
+WebInspector.TimelineCalculator = function()
+{
+    this.reset();
+    this.windowLeft = 0.0;
+    this.windowRight = 1.0;
+}
+
+WebInspector.TimelineCalculator.prototype = {
+    computeBarGraphPercentages: function(record)
+    {
+        var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100;
+        var end = (record.startTime + record._selfTime - this.minimumBoundary) / this.boundarySpan * 100;
+        var endWithChildren = (record._lastChildEndTime - this.minimumBoundary) / this.boundarySpan * 100;
+        var cpuWidth = record._cpuTime / this.boundarySpan * 100;
+        return {start: start, end: end, endWithChildren: endWithChildren, cpuWidth: cpuWidth};
+    },
+
+    computeBarGraphWindowPosition: function(record, clientWidth)
+    {
+        const minWidth = 5;
+        const borderWidth = 4;
+        var workingArea = clientWidth - minWidth - borderWidth;
+        var percentages = this.computeBarGraphPercentages(record);
+        var left = percentages.start / 100 * workingArea;
+        var width = (percentages.end - percentages.start) / 100 * workingArea + minWidth;
+        var widthWithChildren =  (percentages.endWithChildren - percentages.start) / 100 * workingArea;
+        var cpuWidth = percentages.cpuWidth / 100 * workingArea + minWidth;
+        if (percentages.endWithChildren > percentages.end)
+            widthWithChildren += borderWidth + minWidth;
+        return {left: left, width: width, widthWithChildren: widthWithChildren, cpuWidth: cpuWidth};
+    },
+
+    calculateWindow: function()
+    {
+        this.minimumBoundary = this._absoluteMinimumBoundary + this.windowLeft * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary);
+        this.maximumBoundary = this._absoluteMinimumBoundary + this.windowRight * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary);
+        this.boundarySpan = this.maximumBoundary - this.minimumBoundary;
+    },
+
+    reset: function()
+    {
+        this._absoluteMinimumBoundary = -1;
+        this._absoluteMaximumBoundary = -1;
+    },
+
+    updateBoundaries: function(record)
+    {
+        var lowerBound = record.startTime;
+        if (this._absoluteMinimumBoundary === -1 || lowerBound < this._absoluteMinimumBoundary)
+            this._absoluteMinimumBoundary = lowerBound;
+
+        const minimumTimeFrame = 0.1;
+        const minimumDeltaForZeroSizeEvents = 0.01;
+        var upperBound = Math.max(record._lastChildEndTime + minimumDeltaForZeroSizeEvents, lowerBound + minimumTimeFrame);
+        if (this._absoluteMaximumBoundary === -1 || upperBound > this._absoluteMaximumBoundary)
+            this._absoluteMaximumBoundary = upperBound;
+    },
+
+    formatValue: function(value)
+    {
+        return Number.secondsToString(value + this.minimumBoundary - this._absoluteMinimumBoundary);
+    }
+}
+
+
+WebInspector.TimelineRecordListRow = function()
+{
+    this.element = document.createElement("div");
+    this.element.row = this;
+    this.element.style.cursor = "pointer";
+    var iconElement = document.createElement("span");
+    iconElement.className = "timeline-tree-icon";
+    this.element.appendChild(iconElement);
+
+    this._typeElement = document.createElement("span");
+    this._typeElement.className = "type";
+    this.element.appendChild(this._typeElement);
+
+    var separatorElement = document.createElement("span");
+    separatorElement.className = "separator";
+    separatorElement.textContent = " ";
+
+    this._dataElement = document.createElement("span");
+    this._dataElement.className = "data dimmed";
+
+    this.element.appendChild(separatorElement);
+    this.element.appendChild(this._dataElement);
+}
+
+WebInspector.TimelineRecordListRow.prototype = {
+    update: function(record, isEven, calculator, offset)
+    {
+        this._record = record;
+        this._calculator = calculator;
+        this._offset = offset;
+
+        this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : "");
+        this._typeElement.textContent = record.title;
+
+        if (this._dataElement.firstChild)
+            this._dataElement.removeChildren();
+        if (record.details) {
+            var detailsContainer = document.createElement("span");
+            if (typeof record.details === "object") {
+                detailsContainer.appendChild(document.createTextNode("("));
+                detailsContainer.appendChild(record.details);
+                detailsContainer.appendChild(document.createTextNode(")"));
+            } else
+                detailsContainer.textContent = "(" + record.details + ")";
+            this._dataElement.appendChild(detailsContainer);
+        }
+    },
+
+    dispose: function()
+    {
+        this.element.parentElement.removeChild(this.element);
+    }
+}
+
+WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh)
+{
+    this.element = document.createElement("div");
+    this.element.row = this;
+
+    this._barAreaElement = document.createElement("div");
+    this._barAreaElement.className = "timeline-graph-bar-area";
+    this.element.appendChild(this._barAreaElement);
+
+    this._barWithChildrenElement = document.createElement("div");
+    this._barWithChildrenElement.className = "timeline-graph-bar with-children";
+    this._barWithChildrenElement.row = this;
+    this._barAreaElement.appendChild(this._barWithChildrenElement);
+
+    this._barCpuElement = document.createElement("div");
+    this._barCpuElement.className = "timeline-graph-bar cpu"
+    this._barCpuElement.row = this;
+    this._barAreaElement.appendChild(this._barCpuElement);
+
+    this._barElement = document.createElement("div");
+    this._barElement.className = "timeline-graph-bar";
+    this._barElement.row = this;
+    this._barAreaElement.appendChild(this._barElement);
+
+    this._expandElement = new WebInspector.TimelineExpandableElement(graphContainer);
+    this._expandElement._element.addEventListener("click", this._onClick.bind(this));
+
+    this._scheduleRefresh = scheduleRefresh;
+}
+
+WebInspector.TimelineRecordGraphRow.prototype = {
+    update: function(record, isEven, calculator, clientWidth, expandOffset, index)
+    {
+        this._record = record;
+        this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : "");
+        var barPosition = calculator.computeBarGraphWindowPosition(record, clientWidth - expandOffset);
+        this._barWithChildrenElement.style.left = barPosition.left + expandOffset + "px";
+        this._barWithChildrenElement.style.width = barPosition.widthWithChildren + "px";
+        this._barElement.style.left = barPosition.left + expandOffset + "px";
+        this._barElement.style.width =  barPosition.width + "px";
+        this._barCpuElement.style.left = barPosition.left + expandOffset + "px";
+        this._barCpuElement.style.width = barPosition.cpuWidth + "px";
+        this._expandElement._update(record, index, barPosition);
+    },
+
+    _onClick: function(event)
+    {
+        this._record.collapsed = !this._record.collapsed;
+        this._scheduleRefresh();
+    },
+
+    dispose: function()
+    {
+        this.element.parentElement.removeChild(this.element);
+        this._expandElement._dispose();
+    }
+}
+
+WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, panel)
+{
+    var recordTypes = WebInspector.TimelineAgent.RecordType;
+    var style = panel._recordStyles[record.type];
+
+    this.parent = parentRecord;
+    if (parentRecord)
+        parentRecord.children.push(this);
+    this.category = style.category;
+    this.title = style.title;
+    this.startTime = record.startTime / 1000;
+    this.data = record.data;
+    this.type = record.type;
+    this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime;
+    this._selfTime = this.endTime - this.startTime;
+    this._lastChildEndTime = this.endTime;
+    this.originalRecordForTests = record;
+    if (record.stackTrace && record.stackTrace.length)
+        this.stackTrace = record.stackTrace;
+    this.totalHeapSize = record.totalHeapSize;
+    this.usedHeapSize = record.usedHeapSize;
+
+    // Make resource receive record last since request was sent; make finish record last since response received.
+    if (record.type === recordTypes.ResourceSendRequest) {
+        panel._sendRequestRecords[record.data.identifier] = this;
+    } else if (record.type === recordTypes.ScheduleResourceRequest) {
+        panel._scheduledResourceRequests[record.data.url] = this;
+    } else if (record.type === recordTypes.ResourceReceiveResponse) {
+        var sendRequestRecord = panel._sendRequestRecords[record.data.identifier];
+        if (sendRequestRecord) { // False if we started instrumentation in the middle of request.
+            record.data.url = sendRequestRecord.data.url;
+            // Now that we have resource in the collection, recalculate details in order to display short url.
+            sendRequestRecord.details = this._getRecordDetails(sendRequestRecord, panel._sendRequestRecords);
+            if (sendRequestRecord.parent !== panel._rootRecord && sendRequestRecord.parent.type === recordTypes.ScheduleResourceRequest)
+                sendRequestRecord.parent.details = this._getRecordDetails(sendRequestRecord, panel._sendRequestRecords);
+        }
+    } else if (record.type === recordTypes.ResourceReceiveData) {
+        var sendRequestRecord = panel._sendRequestRecords[record.data.identifier];
+        if (sendRequestRecord) // False for main resource.
+            record.data.url = sendRequestRecord.data.url;
+    } else if (record.type === recordTypes.ResourceFinish) {
+        var sendRequestRecord = panel._sendRequestRecords[record.data.identifier];
+        if (sendRequestRecord) // False for main resource.
+            record.data.url = sendRequestRecord.data.url;
+    } else if (record.type === recordTypes.TimerInstall) {
+        this.timeout = record.data.timeout;
+        this.singleShot = record.data.singleShot;
+        panel._timerRecords[record.data.timerId] = this;
+    } else if (record.type === recordTypes.TimerFire) {
+        var timerInstalledRecord = panel._timerRecords[record.data.timerId];
+        if (timerInstalledRecord) {
+            this.callSiteStackTrace = timerInstalledRecord.stackTrace;
+            this.timeout = timerInstalledRecord.timeout;
+            this.singleShot = timerInstalledRecord.singleShot;
+        }
+    }
+    this.details = this._getRecordDetails(record, panel._sendRequestRecords);
+}
+
+WebInspector.TimelinePanel.FormattedRecord.prototype = {
+    isLong: function()
+    {
+        return (this._lastChildEndTime - this.startTime) > WebInspector.TimelinePanel.shortRecordThreshold;
+    },
+
+    get children()
+    {
+        if (!this._children)
+            this._children = [];
+        return this._children;
+    },
+
+    _generateAggregatedInfo: function()
+    {
+        var cell = document.createElement("span");
+        cell.className = "timeline-aggregated-info";
+        for (var index in this._aggregatedStats) {
+            var label = document.createElement("div");
+            label.className = "timeline-aggregated-category timeline-" + index;
+            cell.appendChild(label);
+            var text = document.createElement("span");
+            text.textContent = Number.secondsToString(this._aggregatedStats[index] + 0.0001);
+            cell.appendChild(text);
+        }
+        return cell;
+    },
+
+    _generatePopupContent: function(calculator, categories)
+    {
+        var contentHelper = new WebInspector.TimelinePanel.PopupContentHelper(this.title);
+
+        if (this._children && this._children.length) {
+            contentHelper._appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime + 0.0001));
+            contentHelper._appendElementRow(WebInspector.UIString("Aggregated Time"), this._generateAggregatedInfo());
+        }
+        var text = WebInspector.UIString("%s (at %s)", Number.secondsToString(this._lastChildEndTime - this.startTime),
+            calculator.formatValue(this.startTime - calculator.minimumBoundary));
+        contentHelper._appendTextRow(WebInspector.UIString("Duration"), text);
+
+        const recordTypes = WebInspector.TimelineAgent.RecordType;
+
+        switch (this.type) {
+            case recordTypes.GCEvent:
+                contentHelper._appendTextRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data.usedHeapSizeDelta));
+                break;
+            case recordTypes.TimerInstall:
+            case recordTypes.TimerFire:
+            case recordTypes.TimerRemove:
+                contentHelper._appendTextRow(WebInspector.UIString("Timer ID"), this.data.timerId);
+                if (typeof this.timeout === "number") {
+                    contentHelper._appendTextRow(WebInspector.UIString("Timeout"), Number.secondsToString(this.timeout / 1000));
+                    contentHelper._appendTextRow(WebInspector.UIString("Repeats"), !this.singleShot);
+                }
+                break;
+            case recordTypes.FunctionCall:
+                contentHelper._appendLinkRow(WebInspector.UIString("Location"), this.data.scriptName, this.data.scriptLine);
+                break;
+            case recordTypes.ScheduleResourceRequest:
+            case recordTypes.ResourceSendRequest:
+            case recordTypes.ResourceReceiveResponse:
+            case recordTypes.ResourceReceiveData:
+            case recordTypes.ResourceFinish:
+                contentHelper._appendLinkRow(WebInspector.UIString("Resource"), this.data.url);
+                if (this.data.requestMethod)
+                    contentHelper._appendTextRow(WebInspector.UIString("Request Method"), this.data.requestMethod);
+                if (typeof this.data.statusCode === "number")
+                    contentHelper._appendTextRow(WebInspector.UIString("Status Code"), this.data.statusCode);
+                if (this.data.mimeType)
+                    contentHelper._appendTextRow(WebInspector.UIString("MIME Type"), this.data.mimeType);
+                if (typeof this.data.expectedContentLength === "number" && this.data.expectedContentLength !== -1)
+                    contentHelper._appendTextRow(WebInspector.UIString("Expected Content Length"), this.data.expectedContentLength);
+                break;
+            case recordTypes.EvaluateScript:
+                if (this.data && this.data.url)
+                    contentHelper._appendLinkRow(WebInspector.UIString("Script"), this.data.url, this.data.lineNumber);
+                break;
+            case recordTypes.Paint:
+                contentHelper._appendTextRow(WebInspector.UIString("Location"), WebInspector.UIString("(%d, %d)", this.data.x, this.data.y));
+                contentHelper._appendTextRow(WebInspector.UIString("Dimensions"), WebInspector.UIString("%d × %d", this.data.width, this.data.height));
+            case recordTypes.RecalculateStyles: // We don't want to see default details.
+                break;
+            default:
+                if (this.details)
+                    contentHelper._appendTextRow(WebInspector.UIString("Details"), this.details);
+                break;
+        }
+
+        if (this.data.scriptName && this.type !== recordTypes.FunctionCall)
+            contentHelper._appendLinkRow(WebInspector.UIString("Function Call"), this.data.scriptName, this.data.scriptLine);
+
+        if (this.usedHeapSize)
+            contentHelper._appendTextRow(WebInspector.UIString("Used Heap Size"), WebInspector.UIString("%s of %s", Number.bytesToString(this.usedHeapSize), Number.bytesToString(this.totalHeapSize)));
+
+        if (this.callSiteStackTrace && this.callSiteStackTrace.length)
+            contentHelper._appendStackTrace(WebInspector.UIString("Call Site stack"), this.callSiteStackTrace);
+
+        if (this.stackTrace)
+            contentHelper._appendStackTrace(WebInspector.UIString("Call Stack"), this.stackTrace);
+
+        return contentHelper._contentTable;
+    },
+
+    _getRecordDetails: function(record, sendRequestRecords)
+    {
+        switch (record.type) {
+            case WebInspector.TimelineAgent.RecordType.GCEvent:
+                return WebInspector.UIString("%s collected", Number.bytesToString(record.data.usedHeapSizeDelta));
+            case WebInspector.TimelineAgent.RecordType.TimerFire:
+                return record.data.scriptName ? WebInspector.linkifyResourceAsNode(record.data.scriptName, "scripts", record.data.scriptLine, "", "") : record.data.timerId;
+            case WebInspector.TimelineAgent.RecordType.FunctionCall:
+                return record.data.scriptName ? WebInspector.linkifyResourceAsNode(record.data.scriptName, "scripts", record.data.scriptLine, "", "") : null;
+            case WebInspector.TimelineAgent.RecordType.EventDispatch:
+                return record.data ? record.data.type : null;
+            case WebInspector.TimelineAgent.RecordType.Paint:
+                return record.data.width + "\u2009\u00d7\u2009" + record.data.height;
+            case WebInspector.TimelineAgent.RecordType.TimerInstall:
+            case WebInspector.TimelineAgent.RecordType.TimerRemove:
+                return this.stackTrace ? WebInspector.linkifyResourceAsNode(this.stackTrace[0].scriptName, "scripts", this.stackTrace[0].lineNumber, "", "") : record.data.timerId;
+            case WebInspector.TimelineAgent.RecordType.ParseHTML:
+            case WebInspector.TimelineAgent.RecordType.RecalculateStyles:
+                return this.stackTrace ? WebInspector.linkifyResourceAsNode(this.stackTrace[0].scriptName, "scripts", this.stackTrace[0].lineNumber, "", "") : null;
+            case WebInspector.TimelineAgent.RecordType.EvaluateScript:
+                return record.data.url ? WebInspector.linkifyResourceAsNode(record.data.url, "scripts", record.data.lineNumber, "", "") : null;
+            case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange:
+            case WebInspector.TimelineAgent.RecordType.XHRLoad:
+            case WebInspector.TimelineAgent.RecordType.ScheduleResourceRequest:
+            case WebInspector.TimelineAgent.RecordType.ResourceSendRequest:
+            case WebInspector.TimelineAgent.RecordType.ResourceReceiveData:
+            case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse:
+            case WebInspector.TimelineAgent.RecordType.ResourceFinish:
+                return WebInspector.displayNameForURL(record.data.url);
+            case WebInspector.TimelineAgent.RecordType.MarkTimeline:
+                return record.data.message;
+            default:
+                return null;
+        }
+    },
+
+    _calculateAggregatedStats: function(categories)
+    {
+        this._aggregatedStats = {};
+        for (var category in categories)
+            this._aggregatedStats[category] = 0;
+        this._cpuTime = this._selfTime;
+
+        if (this._children) {
+            for (var index = this._children.length; index; --index) {
+                var child = this._children[index - 1];
+                this._aggregatedStats[child.category.name] += child._selfTime;
+                for (var category in categories)
+                    this._aggregatedStats[category] += child._aggregatedStats[category];
+            }
+            for (var category in this._aggregatedStats)
+                this._cpuTime += this._aggregatedStats[category];
+        }
+    }
+}
+
+WebInspector.TimelinePanel.PopupContentHelper = function(title)
+{
+    this._contentTable = document.createElement("table");;
+    var titleCell = this._createCell(WebInspector.UIString("%s - Details", title), "timeline-details-title");
+    titleCell.colSpan = 2;
+    var titleRow = document.createElement("tr");
+    titleRow.appendChild(titleCell);
+    this._contentTable.appendChild(titleRow);
+}
+
+WebInspector.TimelinePanel.PopupContentHelper.prototype = {
+    _createCell: function(content, styleName)
+    {
+        var text = document.createElement("label");
+        text.appendChild(document.createTextNode(content));
+        var cell = document.createElement("td");
+        cell.className = "timeline-details";
+        if (styleName)
+            cell.className += " " + styleName;
+        cell.textContent = content;
+        return cell;
+    },
+
+    _appendTextRow: function(title, content)
+    {
+        var row = document.createElement("tr");
+        row.appendChild(this._createCell(title, "timeline-details-row-title"));
+        row.appendChild(this._createCell(content, "timeline-details-row-data"));
+        this._contentTable.appendChild(row);
+    },
+
+    _appendElementRow: function(title, content, titleStyle)
+    {
+        var row = document.createElement("tr");
+        var titleCell = this._createCell(title, "timeline-details-row-title");
+        if (titleStyle)
+            titleCell.addStyleClass(titleStyle);
+        row.appendChild(titleCell);
+        var cell = document.createElement("td");
+        cell.className = "timeline-details";
+        cell.appendChild(content);
+        row.appendChild(cell);
+        this._contentTable.appendChild(row);
+    },
+
+    _appendLinkRow: function(title, scriptName, scriptLine)
+    {
+        var link = WebInspector.linkifyResourceAsNode(scriptName, "scripts", scriptLine, "timeline-details");
+        this._appendElementRow(title, link);
+    },
+
+    _appendStackTrace: function(title, stackTrace)
+    {
+        this._appendTextRow("", "");
+        var framesTable = document.createElement("table");
+        for (var i = 0; i < stackTrace.length; ++i) {
+            var stackFrame = stackTrace[i];
+            var row = document.createElement("tr");
+            row.className = "timeline-details";
+            row.appendChild(this._createCell(stackFrame.functionName ? stackFrame.functionName : WebInspector.UIString("(anonymous function)"), "timeline-function-name"));
+            row.appendChild(this._createCell(" @ "));
+            var linkCell = document.createElement("td");
+            linkCell.appendChild(WebInspector.linkifyResourceAsNode(stackFrame.scriptName, "scripts", stackFrame.lineNumber, "timeline-details"));
+            row.appendChild(linkCell);
+            framesTable.appendChild(row);
+        }
+        this._appendElementRow(title, framesTable, "timeline-stacktrace-title");
+    }
+}
+
+WebInspector.TimelineExpandableElement = function(container)
+{
+    this._element = document.createElement("div");
+    this._element.className = "timeline-expandable";
+
+    var leftBorder = document.createElement("div");
+    leftBorder.className = "timeline-expandable-left";
+    this._element.appendChild(leftBorder);
+
+    container.appendChild(this._element);
+}
+
+WebInspector.TimelineExpandableElement.prototype = {
+    _update: function(record, index, barPosition)
+    {
+        const rowHeight = WebInspector.TimelinePanel.rowHeight;
+        if (record._visibleChildrenCount || record._invisibleChildrenCount) {
+            this._element.style.top = index * rowHeight + "px";
+            this._element.style.left = barPosition.left + "px";
+            this._element.style.width = Math.max(12, barPosition.width + 25) + "px";
+            if (!record.collapsed) {
+                this._element.style.height = (record._visibleChildrenCount + 1) * rowHeight + "px";
+                this._element.addStyleClass("timeline-expandable-expanded");
+                this._element.removeStyleClass("timeline-expandable-collapsed");
+            } else {
+                this._element.style.height = rowHeight + "px";
+                this._element.addStyleClass("timeline-expandable-collapsed");
+                this._element.removeStyleClass("timeline-expandable-expanded");
+            }
+            this._element.removeStyleClass("hidden");
+        } else
+            this._element.addStyleClass("hidden");
+    },
+
+    _dispose: function()
+    {
+        this._element.parentElement.removeChild(this._element);
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TopDownProfileDataGridTree.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TopDownProfileDataGridTree.js
new file mode 100644
index 0000000..bfcc25e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TopDownProfileDataGridTree.js
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TopDownProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*TopDownProfileDataGridTree*/ owningTree)
+{
+    var hasChildren = (profileNode.children && profileNode.children.length);
+
+    WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);
+
+    this._remainingChildren = profileNode.children;
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype = {
+    _sharedPopulate: function()
+    {
+        var children = this._remainingChildren;
+        var childrenLength = children.length;
+
+        for (var i = 0; i < childrenLength; ++i)
+            this.appendChild(new WebInspector.TopDownProfileDataGridNode(this.profileView, children[i], this.tree));
+
+        this._remainingChildren = null;
+    },
+
+    _exclude: function(aCallUID)
+    {
+        if (this._remainingChildren)
+            this._populate();
+
+        this._save();
+
+        var children = this.children;
+        var index = this.children.length;
+
+        while (index--)
+            children[index]._exclude(aCallUID);
+
+        var child = this.childrenByCallUID[aCallUID];
+
+        if (child)
+            this._merge(child, true);
+    }
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
+
+WebInspector.TopDownProfileDataGridTree = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode)
+{
+    WebInspector.ProfileDataGridTree.call(this, profileView, profileNode);
+
+    this._remainingChildren = profileNode.children;
+
+    WebInspector.TopDownProfileDataGridNode.prototype._populate.call(this);
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype = {
+    focus: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+    {
+        if (!profileDataGrideNode)
+            return;
+
+        this._save();
+        profileDataGrideNode.savePosition();
+
+        this.children = [profileDataGrideNode];
+        this.totalTime = profileDataGrideNode.totalTime;
+    },
+
+    exclude: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+    {
+        if (!profileDataGrideNode)
+            return;
+
+        this._save();
+
+        var excludedCallUID = profileDataGrideNode.callUID;
+
+        WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(this, excludedCallUID);
+
+        if (this.lastComparator)
+            this.sort(this.lastComparator, true);
+    },
+
+    restore: function()
+    {
+        if (!this._savedChildren)
+            return;
+
+        this.children[0].restorePosition();
+
+        WebInspector.ProfileDataGridTree.prototype.restore.call(this);
+    },
+
+    _merge: WebInspector.TopDownProfileDataGridNode.prototype._merge,
+
+    _sharedPopulate: WebInspector.TopDownProfileDataGridNode.prototype._sharedPopulate
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/parse-js.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/parse-js.js
new file mode 100644
index 0000000..a559145
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/parse-js.js
@@ -0,0 +1,1247 @@
+/***********************************************************************
+
+  A JavaScript tokenizer / parser / beautifier / compressor.
+
+  This version is suitable for Node.js.  With minimal changes (the
+  exports stuff) it should work on any JS platform.
+
+  This file contains the tokenizer/parser.  It is a port to JavaScript
+  of parse-js [1], a JavaScript parser library written in Common Lisp
+  by Marijn Haverbeke.  Thank you Marijn!
+
+  [1] http://marijn.haverbeke.nl/parse-js/
+
+  Exported functions:
+
+    - tokenizer(code) -- returns a function.  Call the returned
+      function to fetch the next token.
+
+    - parse(code) -- returns an AST of the given JavaScript code.
+
+  -------------------------------- (C) ---------------------------------
+
+                           Author: Mihai Bazon
+                         <mihai.bazon@gmail.com>
+                       http://mihai.bazon.net/blog
+
+  Distributed under the BSD license:
+
+    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+    Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+        * Redistributions of source code must retain the above
+          copyright notice, this list of conditions and the following
+          disclaimer.
+
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials
+          provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ ***********************************************************************/
+
+/* -----[ Tokenizer (constants) ]----- */
+
+var KEYWORDS = array_to_hash([
+        "break",
+        "case",
+        "catch",
+        "const",
+        "continue",
+        "default",
+        "delete",
+        "do",
+        "else",
+        "finally",
+        "for",
+        "function",
+        "if",
+        "in",
+        "instanceof",
+        "new",
+        "return",
+        "switch",
+        "throw",
+        "try",
+        "typeof",
+        "var",
+        "void",
+        "while",
+        "with"
+]);
+
+var RESERVED_WORDS = array_to_hash([
+        "abstract",
+        "boolean",
+        "byte",
+        "char",
+        "class",
+        "debugger",
+        "double",
+        "enum",
+        "export",
+        "extends",
+        "final",
+        "float",
+        "goto",
+        "implements",
+        "import",
+        "int",
+        "interface",
+        "long",
+        "native",
+        "package",
+        "private",
+        "protected",
+        "public",
+        "short",
+        "static",
+        "super",
+        "synchronized",
+        "throws",
+        "transient",
+        "volatile"
+]);
+
+var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
+        "return",
+        "new",
+        "delete",
+        "throw",
+        "else",
+        "case"
+]);
+
+var KEYWORDS_ATOM = array_to_hash([
+        "false",
+        "null",
+        "true",
+        "undefined"
+]);
+
+var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
+
+var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
+var RE_OCT_NUMBER = /^0[0-7]+$/;
+var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
+
+var OPERATORS = array_to_hash([
+        "in",
+        "instanceof",
+        "typeof",
+        "new",
+        "void",
+        "delete",
+        "++",
+        "--",
+        "+",
+        "-",
+        "!",
+        "~",
+        "&",
+        "|",
+        "^",
+        "*",
+        "/",
+        "%",
+        ">>",
+        "<<",
+        ">>>",
+        "<",
+        ">",
+        "<=",
+        ">=",
+        "==",
+        "===",
+        "!=",
+        "!==",
+        "?",
+        "=",
+        "+=",
+        "-=",
+        "/=",
+        "*=",
+        "%=",
+        ">>=",
+        "<<=",
+        ">>>=",
+        "%=",
+        "|=",
+        "^=",
+        "&=",
+        "&&",
+        "||"
+]);
+
+var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t"));
+
+var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
+
+var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
+
+var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
+
+/* -----[ Tokenizer ]----- */
+
+function is_alphanumeric_char(ch) {
+        ch = ch.charCodeAt(0);
+        return (ch >= 48 && ch <= 57) ||
+                (ch >= 65 && ch <= 90) ||
+                (ch >= 97 && ch <= 122);
+};
+
+function is_identifier_char(ch) {
+        return is_alphanumeric_char(ch) || ch == "$" || ch == "_";
+};
+
+function is_digit(ch) {
+        ch = ch.charCodeAt(0);
+        return ch >= 48 && ch <= 57;
+};
+
+function parse_js_number(num) {
+        if (RE_HEX_NUMBER.test(num)) {
+                return parseInt(num.substr(2), 16);
+        } else if (RE_OCT_NUMBER.test(num)) {
+                return parseInt(num.substr(1), 8);
+        } else if (RE_DEC_NUMBER.test(num)) {
+                return parseFloat(num);
+        }
+};
+
+function JS_Parse_Error(message, line, col, pos) {
+        this.message = message;
+        this.line = line;
+        this.col = col;
+        this.pos = pos;
+        try {
+                ({})();
+        } catch(ex) {
+                this.stack = ex.stack;
+        };
+};
+
+JS_Parse_Error.prototype.toString = function() {
+        return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
+};
+
+function js_error(message, line, col, pos) {
+        throw new JS_Parse_Error(message, line, col, pos);
+};
+
+function is_token(token, type, val) {
+        return token.type == type && (val == null || token.value == val);
+};
+
+var EX_EOF = {};
+
+function tokenizer($TEXT) {
+
+        var S = {
+                text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
+                pos             : 0,
+                tokpos          : 0,
+                line            : 0,
+                tokline         : 0,
+                col             : 0,
+                tokcol          : 0,
+                newline_before  : false,
+                regex_allowed   : false,
+                comments_before : []
+        };
+
+        function peek() { return S.text.charAt(S.pos); };
+
+        function next(signal_eof) {
+                var ch = S.text.charAt(S.pos++);
+                if (signal_eof && !ch)
+                        throw EX_EOF;
+                if (ch == "\n") {
+                        S.newline_before = true;
+                        ++S.line;
+                        S.col = 0;
+                } else {
+                        ++S.col;
+                }
+                return ch;
+        };
+
+        function eof() {
+                return !S.peek();
+        };
+
+        function find(what, signal_eof) {
+                var pos = S.text.indexOf(what, S.pos);
+                if (signal_eof && pos == -1) throw EX_EOF;
+                return pos;
+        };
+
+        function start_token() {
+                S.tokline = S.line;
+                S.tokcol = S.col;
+                S.tokpos = S.pos;
+        };
+
+        function token(type, value, is_comment) {
+                S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
+                                   (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
+                                   (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
+                var ret = {
+                        type  : type,
+                        value : value,
+                        line  : S.tokline,
+                        col   : S.tokcol,
+                        pos   : S.tokpos,
+                        nlb   : S.newline_before
+                };
+                if (!is_comment) {
+                        ret.comments_before = S.comments_before;
+                        S.comments_before = [];
+                }
+                S.newline_before = false;
+                return ret;
+        };
+
+        function skip_whitespace() {
+                while (HOP(WHITESPACE_CHARS, peek()))
+                        next();
+        };
+
+        function read_while(pred) {
+                var ret = "", ch = peek(), i = 0;
+                while (ch && pred(ch, i++)) {
+                        ret += next();
+                        ch = peek();
+                }
+                return ret;
+        };
+
+        function parse_error(err) {
+                js_error(err, S.tokline, S.tokcol, S.tokpos);
+        };
+
+        function read_num(prefix) {
+                var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
+                var num = read_while(function(ch, i){
+                        if (ch == "x" || ch == "X") {
+                                if (has_x) return false;
+                                return has_x = true;
+                        }
+                        if (!has_x && (ch == "E" || ch == "e")) {
+                                if (has_e) return false;
+                                return has_e = after_e = true;
+                        }
+                        if (ch == "-") {
+                                if (after_e || (i == 0 && !prefix)) return true;
+                                return false;
+                        }
+                        if (ch == "+") return after_e;
+                        after_e = false;
+                        if (ch == ".") {
+                                if (!has_dot)
+                                        return has_dot = true;
+                                return false;
+                        }
+                        return is_alphanumeric_char(ch);
+                });
+                if (prefix)
+                        num = prefix + num;
+                var valid = parse_js_number(num);
+                if (!isNaN(valid)) {
+                        return token("num", valid);
+                } else {
+                        parse_error("Invalid syntax: " + num);
+                }
+        };
+
+        function read_escaped_char() {
+                var ch = next(true);
+                switch (ch) {
+                    case "n" : return "\n";
+                    case "r" : return "\r";
+                    case "t" : return "\t";
+                    case "b" : return "\b";
+                    case "v" : return "\v";
+                    case "f" : return "\f";
+                    case "0" : return "\0";
+                    case "x" : return String.fromCharCode(hex_bytes(2));
+                    case "u" : return String.fromCharCode(hex_bytes(4));
+                    default  : return ch;
+                }
+        };
+
+        function hex_bytes(n) {
+                var num = 0;
+                for (; n > 0; --n) {
+                        var digit = parseInt(next(true), 16);
+                        if (isNaN(digit))
+                                parse_error("Invalid hex-character pattern in string");
+                        num = (num << 4) | digit;
+                }
+                return num;
+        };
+
+        function read_string() {
+                return with_eof_error("Unterminated string constant", function(){
+                        var quote = next(), ret = "";
+                        for (;;) {
+                                var ch = next(true);
+                                if (ch == "\\") ch = read_escaped_char();
+                                else if (ch == quote) break;
+                                ret += ch;
+                        }
+                        return token("string", ret);
+                });
+        };
+
+        function read_line_comment() {
+                next();
+                var i = find("\n"), ret;
+                if (i == -1) {
+                        ret = S.text.substr(S.pos);
+                        S.pos = S.text.length;
+                } else {
+                        ret = S.text.substring(S.pos, i);
+                        S.pos = i;
+                }
+                return token("comment1", ret, true);
+        };
+
+        function read_multiline_comment() {
+                next();
+                return with_eof_error("Unterminated multiline comment", function(){
+                        var i = find("*/", true),
+                            text = S.text.substring(S.pos, i),
+                            tok = token("comment2", text, true);
+                        S.pos = i + 2;
+                        S.line += text.split("\n").length - 1;
+                        S.newline_before = text.indexOf("\n") >= 0;
+                        return tok;
+                });
+        };
+
+        function read_regexp() {
+                return with_eof_error("Unterminated regular expression", function(){
+                        var prev_backslash = false, regexp = "", ch, in_class = false;
+                        while ((ch = next(true))) if (prev_backslash) {
+                                regexp += "\\" + ch;
+                                prev_backslash = false;
+                        } else if (ch == "[") {
+                                in_class = true;
+                                regexp += ch;
+                        } else if (ch == "]" && in_class) {
+                                in_class = false;
+                                regexp += ch;
+                        } else if (ch == "/" && !in_class) {
+                                break;
+                        } else if (ch == "\\") {
+                                prev_backslash = true;
+                        } else {
+                                regexp += ch;
+                        }
+                        var mods = read_while(function(ch){
+                                return HOP(REGEXP_MODIFIERS, ch);
+                        });
+                        return token("regexp", [ regexp, mods ]);
+                });
+        };
+
+        function read_operator(prefix) {
+                function grow(op) {
+                        if (!peek()) return op;
+                        var bigger = op + peek();
+                        if (HOP(OPERATORS, bigger)) {
+                                next();
+                                return grow(bigger);
+                        } else {
+                                return op;
+                        }
+                };
+                return token("operator", grow(prefix || next()));
+        };
+
+        function handle_slash() {
+                next();
+                var regex_allowed = S.regex_allowed;
+                switch (peek()) {
+                    case "/":
+                        S.comments_before.push(read_line_comment());
+                        S.regex_allowed = regex_allowed;
+                        return next_token();
+                    case "*":
+                        S.comments_before.push(read_multiline_comment());
+                        S.regex_allowed = regex_allowed;
+                        return next_token();
+                }
+                return S.regex_allowed ? read_regexp() : read_operator("/");
+        };
+
+        function handle_dot() {
+                next();
+                return is_digit(peek())
+                        ? read_num(".")
+                        : token("punc", ".");
+        };
+
+        function read_word() {
+                var word = read_while(is_identifier_char);
+                return !HOP(KEYWORDS, word)
+                        ? token("name", word)
+                        : HOP(OPERATORS, word)
+                        ? token("operator", word)
+                        : HOP(KEYWORDS_ATOM, word)
+                        ? token("atom", word)
+                        : token("keyword", word);
+        };
+
+        function with_eof_error(eof_error, cont) {
+                try {
+                        return cont();
+                } catch(ex) {
+                        if (ex === EX_EOF) parse_error(eof_error);
+                        else throw ex;
+                }
+        };
+
+        function next_token(force_regexp) {
+                if (force_regexp)
+                        return read_regexp();
+                skip_whitespace();
+                start_token();
+                var ch = peek();
+                if (!ch) return token("eof");
+                if (is_digit(ch)) return read_num();
+                if (ch == '"' || ch == "'") return read_string();
+                if (HOP(PUNC_CHARS, ch)) return token("punc", next());
+                if (ch == ".") return handle_dot();
+                if (ch == "/") return handle_slash();
+                if (HOP(OPERATOR_CHARS, ch)) return read_operator();
+                if (is_identifier_char(ch)) return read_word();
+                parse_error("Unexpected character '" + ch + "'");
+        };
+
+        next_token.context = function(nc) {
+                if (nc) S = nc;
+                return S;
+        };
+
+        return next_token;
+
+};
+
+/* -----[ Parser (constants) ]----- */
+
+var UNARY_PREFIX = array_to_hash([
+        "typeof",
+        "void",
+        "delete",
+        "--",
+        "++",
+        "!",
+        "~",
+        "-",
+        "+"
+]);
+
+var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
+
+var ASSIGNMENT = (function(a, ret, i){
+        while (i < a.length) {
+                ret[a[i]] = a[i].substr(0, a[i].length - 1);
+                i++;
+        }
+        return ret;
+})(
+        ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
+        { "=": true },
+        0
+);
+
+var PRECEDENCE = (function(a, ret){
+        for (var i = 0, n = 1; i < a.length; ++i, ++n) {
+                var b = a[i];
+                for (var j = 0; j < b.length; ++j) {
+                        ret[b[j]] = n;
+                }
+        }
+        return ret;
+})(
+        [
+                ["||"],
+                ["&&"],
+                ["|"],
+                ["^"],
+                ["&"],
+                ["==", "===", "!=", "!=="],
+                ["<", ">", "<=", ">=", "in", "instanceof"],
+                [">>", "<<", ">>>"],
+                ["+", "-"],
+                ["*", "/", "%"]
+        ],
+        {}
+);
+
+var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
+
+var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
+
+/* -----[ Parser ]----- */
+
+function NodeWithToken(str, start, end) {
+        this.name = str;
+        this.start = start;
+        this.end = end;
+};
+
+NodeWithToken.prototype.toString = function() { return this.name; };
+
+function parse($TEXT, strict_mode, embed_tokens) {
+
+        var S = {
+                input       : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
+                token       : null,
+                prev        : null,
+                peeked      : null,
+                in_function : 0,
+                in_loop     : 0,
+                labels      : []
+        };
+
+        S.token = next();
+
+        function is(type, value) {
+                return is_token(S.token, type, value);
+        };
+
+        function peek() { return S.peeked || (S.peeked = S.input()); };
+
+        function next() {
+                S.prev = S.token;
+                if (S.peeked) {
+                        S.token = S.peeked;
+                        S.peeked = null;
+                } else {
+                        S.token = S.input();
+                }
+                return S.token;
+        };
+
+        function prev() {
+                return S.prev;
+        };
+
+        function croak(msg, line, col, pos) {
+                var ctx = S.input.context();
+                js_error(msg,
+                         line != null ? line : ctx.tokline,
+                         col != null ? col : ctx.tokcol,
+                         pos != null ? pos : ctx.tokpos);
+        };
+
+        function token_error(token, msg) {
+                croak(msg, token.line, token.col);
+        };
+
+        function unexpected(token) {
+                if (token == null)
+                        token = S.token;
+                token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
+        };
+
+        function expect_token(type, val) {
+                if (is(type, val)) {
+                        return next();
+                }
+                token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
+        };
+
+        function expect(punc) { return expect_token("punc", punc); };
+
+        function can_insert_semicolon() {
+                return !strict_mode && (
+                        S.token.nlb || is("eof") || is("punc", "}")
+                );
+        };
+
+        function semicolon() {
+                if (is("punc", ";")) next();
+                else if (!can_insert_semicolon()) unexpected();
+        };
+
+        function as() {
+                return slice(arguments);
+        };
+
+        function parenthesised() {
+                expect("(");
+                var ex = expression();
+                expect(")");
+                return ex;
+        };
+
+        function add_tokens(str, start, end) {
+                return new NodeWithToken(str, start, end);
+        };
+
+        var statement = embed_tokens ? function() {
+                var start = S.token;
+                var stmt = $statement();
+                stmt[0] = add_tokens(stmt[0], start, prev());
+                return stmt;
+        } : $statement;
+
+        function $statement() {
+                if (is("operator", "/")) {
+                        S.peeked = null;
+                        S.token = S.input(true); // force regexp
+                }
+                switch (S.token.type) {
+                    case "num":
+                    case "string":
+                    case "regexp":
+                    case "operator":
+                    case "atom":
+                        return simple_statement();
+
+                    case "name":
+                        return is_token(peek(), "punc", ":")
+                                ? labeled_statement(prog1(S.token.value, next, next))
+                                : simple_statement();
+
+                    case "punc":
+                        switch (S.token.value) {
+                            case "{":
+                                return as("block", block_());
+                            case "[":
+                            case "(":
+                                return simple_statement();
+                            case ";":
+                                next();
+                                return as("block");
+                            default:
+                                unexpected();
+                        }
+
+                    case "keyword":
+                        switch (prog1(S.token.value, next)) {
+                            case "break":
+                                return break_cont("break");
+
+                            case "continue":
+                                return break_cont("continue");
+
+                            case "debugger":
+                                semicolon();
+                                return as("debugger");
+
+                            case "do":
+                                return (function(body){
+                                        expect_token("keyword", "while");
+                                        return as("do", prog1(parenthesised, semicolon), body);
+                                })(in_loop(statement));
+
+                            case "for":
+                                return for_();
+
+                            case "function":
+                                return function_(true);
+
+                            case "if":
+                                return if_();
+
+                            case "return":
+                                if (S.in_function == 0)
+                                        croak("'return' outside of function");
+                                return as("return",
+                                          is("punc", ";")
+                                          ? (next(), null)
+                                          : can_insert_semicolon()
+                                          ? null
+                                          : prog1(expression, semicolon));
+
+                            case "switch":
+                                return as("switch", parenthesised(), switch_block_());
+
+                            case "throw":
+                                return as("throw", prog1(expression, semicolon));
+
+                            case "try":
+                                return try_();
+
+                            case "var":
+                                return prog1(var_, semicolon);
+
+                            case "const":
+                                return prog1(const_, semicolon);
+
+                            case "while":
+                                return as("while", parenthesised(), in_loop(statement));
+
+                            case "with":
+                                return as("with", parenthesised(), statement());
+
+                            default:
+                                unexpected();
+                        }
+                }
+        };
+
+        function labeled_statement(label) {
+                S.labels.push(label);
+                var start = S.token, stat = statement();
+                if (strict_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
+                        unexpected(start);
+                S.labels.pop();
+                return as("label", label, stat);
+        };
+
+        function simple_statement() {
+                return as("stat", prog1(expression, semicolon));
+        };
+
+        function break_cont(type) {
+                var name = is("name") ? S.token.value : null;
+                if (name != null) {
+                        next();
+                        if (!member(name, S.labels))
+                                croak("Label " + name + " without matching loop or statement");
+                }
+                else if (S.in_loop == 0)
+                        croak(type + " not inside a loop or switch");
+                semicolon();
+                return as(type, name);
+        };
+
+        function for_() {
+                expect("(");
+                var has_var = is("keyword", "var");
+                if (has_var)
+                        next();
+                if (is("name") && is_token(peek(), "operator", "in")) {
+                        // for (i in foo)
+                        var name = S.token.value;
+                        next(); next();
+                        var obj = expression();
+                        expect(")");
+                        return as("for-in", has_var, name, obj, in_loop(statement));
+                } else {
+                        // classic for
+                        var init = is("punc", ";") ? null : has_var ? var_() : expression();
+                        expect(";");
+                        var test = is("punc", ";") ? null : expression();
+                        expect(";");
+                        var step = is("punc", ")") ? null : expression();
+                        expect(")");
+                        return as("for", init, test, step, in_loop(statement));
+                }
+        };
+
+        function function_(in_statement) {
+                var name = is("name") ? prog1(S.token.value, next) : null;
+                if (in_statement && !name)
+                        unexpected();
+                expect("(");
+                return as(in_statement ? "defun" : "function",
+                          name,
+                          // arguments
+                          (function(first, a){
+                                  while (!is("punc", ")")) {
+                                          if (first) first = false; else expect(",");
+                                          if (!is("name")) unexpected();
+                                          a.push(S.token.value);
+                                          next();
+                                  }
+                                  next();
+                                  return a;
+                          })(true, []),
+                          // body
+                          (function(){
+                                  ++S.in_function;
+                                  var loop = S.in_loop;
+                                  S.in_loop = 0;
+                                  var a = block_();
+                                  --S.in_function;
+                                  S.in_loop = loop;
+                                  return a;
+                          })());
+        };
+
+        function if_() {
+                var cond = parenthesised(), body = statement(), belse;
+                if (is("keyword", "else")) {
+                        next();
+                        belse = statement();
+                }
+                return as("if", cond, body, belse);
+        };
+
+        function block_() {
+                expect("{");
+                var a = [];
+                while (!is("punc", "}")) {
+                        if (is("eof")) unexpected();
+                        a.push(statement());
+                }
+                next();
+                return a;
+        };
+
+        var switch_block_ = curry(in_loop, function(){
+                expect("{");
+                var a = [], cur = null;
+                while (!is("punc", "}")) {
+                        if (is("eof")) unexpected();
+                        if (is("keyword", "case")) {
+                                next();
+                                cur = [];
+                                a.push([ expression(), cur ]);
+                                expect(":");
+                        }
+                        else if (is("keyword", "default")) {
+                                next();
+                                expect(":");
+                                cur = [];
+                                a.push([ null, cur ]);
+                        }
+                        else {
+                                if (!cur) unexpected();
+                                cur.push(statement());
+                        }
+                }
+                next();
+                return a;
+        });
+
+        function try_() {
+                var body = block_(), bcatch, bfinally;
+                if (is("keyword", "catch")) {
+                        next();
+                        expect("(");
+                        if (!is("name"))
+                                croak("Name expected");
+                        var name = S.token.value;
+                        next();
+                        expect(")");
+                        bcatch = [ name, block_() ];
+                }
+                if (is("keyword", "finally")) {
+                        next();
+                        bfinally = block_();
+                }
+                if (!bcatch && !bfinally)
+                        croak("Missing catch/finally blocks");
+                return as("try", body, bcatch, bfinally);
+        };
+
+        function vardefs() {
+                var a = [];
+                for (;;) {
+                        if (!is("name"))
+                                unexpected();
+                        var name = S.token.value;
+                        next();
+                        if (is("operator", "=")) {
+                                next();
+                                a.push([ name, expression(false) ]);
+                        } else {
+                                a.push([ name ]);
+                        }
+                        if (!is("punc", ","))
+                                break;
+                        next();
+                }
+                return a;
+        };
+
+        function var_() {
+                return as("var", vardefs());
+        };
+
+        function const_() {
+                return as("const", vardefs());
+        };
+
+        function new_() {
+                var newexp = expr_atom(false), args;
+                if (is("punc", "(")) {
+                        next();
+                        args = expr_list(")");
+                } else {
+                        args = [];
+                }
+                return subscripts(as("new", newexp, args), true);
+        };
+
+        function expr_atom(allow_calls) {
+                if (is("operator", "new")) {
+                        next();
+                        return new_();
+                }
+                if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
+                        return make_unary("unary-prefix",
+                                          prog1(S.token.value, next),
+                                          expr_atom(allow_calls));
+                }
+                if (is("punc")) {
+                        switch (S.token.value) {
+                            case "(":
+                                next();
+                                return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
+                            case "[":
+                                next();
+                                return subscripts(array_(), allow_calls);
+                            case "{":
+                                next();
+                                return subscripts(object_(), allow_calls);
+                        }
+                        unexpected();
+                }
+                if (is("keyword", "function")) {
+                        next();
+                        return subscripts(function_(false), allow_calls);
+                }
+                if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
+                        var atom = S.token.type == "regexp"
+                                ? as("regexp", S.token.value[0], S.token.value[1])
+                                : as(S.token.type, S.token.value);
+                        return subscripts(prog1(atom, next), allow_calls);
+                }
+                unexpected();
+        };
+
+        function expr_list(closing, allow_trailing_comma, allow_empty) {
+                var first = true, a = [];
+                while (!is("punc", closing)) {
+                        if (first) first = false; else expect(",");
+                        if (allow_trailing_comma && is("punc", closing)) break;
+                        if (is("punc", ",") && allow_empty) {
+                                a.push([ "atom", "undefined" ]);
+                        } else {
+                                a.push(expression(false));
+                        }
+                }
+                next();
+                return a;
+        };
+
+        function array_() {
+                return as("array", expr_list("]", !strict_mode, true));
+        };
+
+        function object_() {
+                var first = true, a = [];
+                while (!is("punc", "}")) {
+                        if (first) first = false; else expect(",");
+                        if (!strict_mode && is("punc", "}"))
+                                // allow trailing comma
+                                break;
+                        var type = S.token.type;
+                        var name = as_property_name();
+                        if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
+                                a.push([ as_name(), function_(false), name ]);
+                        } else {
+                                expect(":");
+                                a.push([ name, expression(false) ]);
+                        }
+                }
+                next();
+                return as("object", a);
+        };
+
+        function as_property_name() {
+                switch (S.token.type) {
+                    case "num":
+                    case "string":
+                        return prog1(S.token.value, next);
+                }
+                return as_name();
+        };
+
+        function as_name() {
+                switch (S.token.type) {
+                    case "name":
+                    case "operator":
+                    case "keyword":
+                    case "atom":
+                        return prog1(S.token.value, next);
+                    default:
+                        unexpected();
+                }
+        };
+
+        function subscripts(expr, allow_calls) {
+                if (is("punc", ".")) {
+                        next();
+                        return subscripts(as("dot", expr, as_name()), allow_calls);
+                }
+                if (is("punc", "[")) {
+                        next();
+                        return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
+                }
+                if (allow_calls && is("punc", "(")) {
+                        next();
+                        return subscripts(as("call", expr, expr_list(")")), true);
+                }
+                if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) {
+                        return prog1(curry(make_unary, "unary-postfix", S.token.value, expr),
+                                     next);
+                }
+                return expr;
+        };
+
+        function make_unary(tag, op, expr) {
+                if ((op == "++" || op == "--") && !is_assignable(expr))
+                        croak("Invalid use of " + op + " operator");
+                return as(tag, op, expr);
+        };
+
+        function expr_op(left, min_prec) {
+                var op = is("operator") ? S.token.value : null;
+                var prec = op != null ? PRECEDENCE[op] : null;
+                if (prec != null && prec > min_prec) {
+                        next();
+                        var right = expr_op(expr_atom(true), prec);
+                        return expr_op(as("binary", op, left, right), min_prec);
+                }
+                return left;
+        };
+
+        function expr_ops() {
+                return expr_op(expr_atom(true), 0);
+        };
+
+        function maybe_conditional() {
+                var expr = expr_ops();
+                if (is("operator", "?")) {
+                        next();
+                        var yes = expression(false);
+                        expect(":");
+                        return as("conditional", expr, yes, expression(false));
+                }
+                return expr;
+        };
+
+        function is_assignable(expr) {
+                switch (expr[0]) {
+                    case "dot":
+                    case "sub":
+                        return true;
+                    case "name":
+                        return expr[1] != "this";
+                }
+        };
+
+        function maybe_assign() {
+                var left = maybe_conditional(), val = S.token.value;
+                if (is("operator") && HOP(ASSIGNMENT, val)) {
+                        if (is_assignable(left)) {
+                                next();
+                                return as("assign", ASSIGNMENT[val], left, maybe_assign());
+                        }
+                        croak("Invalid assignment");
+                }
+                return left;
+        };
+
+        function expression(commas) {
+                if (arguments.length == 0)
+                        commas = true;
+                var expr = maybe_assign();
+                if (commas && is("punc", ",")) {
+                        next();
+                        return as("seq", expr, expression());
+                }
+                return expr;
+        };
+
+        function in_loop(cont) {
+                try {
+                        ++S.in_loop;
+                        return cont();
+                } finally {
+                        --S.in_loop;
+                }
+        };
+
+        return as("toplevel", (function(a){
+                while (!is("eof"))
+                        a.push(statement());
+                return a;
+        })([]));
+
+};
+
+/* -----[ Utilities ]----- */
+
+function curry(f) {
+        var args = slice(arguments, 1);
+        return function() { return f.apply(this, args.concat(slice(arguments))); };
+};
+
+function prog1(ret) {
+        if (ret instanceof Function)
+                ret = ret();
+        for (var i = 1, n = arguments.length; --n > 0; ++i)
+                arguments[i]();
+        return ret;
+};
+
+function array_to_hash(a) {
+        var ret = {};
+        for (var i = 0; i < a.length; ++i)
+                ret[a[i]] = true;
+        return ret;
+};
+
+function slice(a, start) {
+        return Array.prototype.slice.call(a, start == null ? 0 : start);
+};
+
+function characters(str) {
+        return str.split("");
+};
+
+function member(name, array) {
+        for (var i = array.length; --i >= 0;)
+                if (array[i] === name)
+                        return true;
+        return false;
+};
+
+function HOP(obj, prop) {
+        return Object.prototype.hasOwnProperty.call(obj, prop);
+};
+
+/* -----[ Exports ]----- */
+
+exports.tokenizer = tokenizer;
+exports.parse = parse;
+exports.slice = slice;
+exports.curry = curry;
+exports.member = member;
+exports.array_to_hash = array_to_hash;
+exports.PRECEDENCE = PRECEDENCE;
+exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
+exports.RESERVED_WORDS = RESERVED_WORDS;
+exports.KEYWORDS = KEYWORDS;
+exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
+exports.OPERATORS = OPERATORS;
+exports.is_alphanumeric_char = is_alphanumeric_char;
+exports.is_identifier_char = is_identifier_char;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/process.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/process.js
new file mode 100755
index 0000000..5e32dd0
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/UglifyJS/process.js
@@ -0,0 +1,1498 @@
+/***********************************************************************
+
+  A JavaScript tokenizer / parser / beautifier / compressor.
+
+  This version is suitable for Node.js.  With minimal changes (the
+  exports stuff) it should work on any JS platform.
+
+  This file implements some AST processors.  They work on data built
+  by parse-js.
+
+  Exported functions:
+
+    - ast_mangle(ast, include_toplevel) -- mangles the
+      variable/function names in the AST.  Returns an AST.  Pass true
+      as second argument to mangle toplevel names too.
+
+    - ast_squeeze(ast) -- employs various optimizations to make the
+      final generated code even smaller.  Returns an AST.
+
+    - gen_code(ast, beautify) -- generates JS code from the AST.  Pass
+      true (or an object, see the code for some options) as second
+      argument to get "pretty" (indented) code.
+
+  -------------------------------- (C) ---------------------------------
+
+                           Author: Mihai Bazon
+                         <mihai.bazon@gmail.com>
+                       http://mihai.bazon.net/blog
+
+  Distributed under the BSD license:
+
+    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+        * Redistributions of source code must retain the above
+          copyright notice, this list of conditions and the following
+          disclaimer.
+
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials
+          provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ ***********************************************************************/
+
+var jsp = require("./parse-js"),
+    slice = jsp.slice,
+    member = jsp.member,
+    PRECEDENCE = jsp.PRECEDENCE,
+    OPERATORS = jsp.OPERATORS;
+
+/* -----[ helper for AST traversal ]----- */
+
+function ast_walker(ast) {
+        function _vardefs(defs) {
+                return [ this[0], MAP(defs, function(def){
+                        var a = [ def[0] ];
+                        if (def.length > 1)
+                                a[1] = walk(def[1]);
+                        return a;
+                }) ];
+        };
+        var walkers = {
+                "string": function(str) {
+                        return [ this[0], str ];
+                },
+                "num": function(num) {
+                        return [ this[0], num ];
+                },
+                "name": function(name) {
+                        return [ this[0], name ];
+                },
+                "toplevel": function(statements) {
+                        return [ this[0], MAP(statements, walk) ];
+                },
+                "block": function(statements) {
+                        var out = [ this[0] ];
+                        if (statements != null)
+                                out.push(MAP(statements, walk));
+                        return out;
+                },
+                "var": _vardefs,
+                "const": _vardefs,
+                "try": function(t, c, f) {
+                        return [
+                                this[0],
+                                MAP(t, walk),
+                                c != null ? [ c[0], MAP(c[1], walk) ] : null,
+                                f != null ? MAP(f, walk) : null
+                        ];
+                },
+                "throw": function(expr) {
+                        return [ this[0], walk(expr) ];
+                },
+                "new": function(ctor, args) {
+                        return [ this[0], walk(ctor), MAP(args, walk) ];
+                },
+                "switch": function(expr, body) {
+                        return [ this[0], walk(expr), MAP(body, function(branch){
+                                return [ branch[0] ? walk(branch[0]) : null,
+                                         MAP(branch[1], walk) ];
+                        }) ];
+                },
+                "break": function(label) {
+                        return [ this[0], label ];
+                },
+                "continue": function(label) {
+                        return [ this[0], label ];
+                },
+                "conditional": function(cond, t, e) {
+                        return [ this[0], walk(cond), walk(t), walk(e) ];
+                },
+                "assign": function(op, lvalue, rvalue) {
+                        return [ this[0], op, walk(lvalue), walk(rvalue) ];
+                },
+                "dot": function(expr) {
+                        return [ this[0], walk(expr) ].concat(slice(arguments, 1));
+                },
+                "call": function(expr, args) {
+                        return [ this[0], walk(expr), MAP(args, walk) ];
+                },
+                "function": function(name, args, body) {
+                        return [ this[0], name, args.slice(), MAP(body, walk) ];
+                },
+                "defun": function(name, args, body) {
+                        return [ this[0], name, args.slice(), MAP(body, walk) ];
+                },
+                "if": function(conditional, t, e) {
+                        return [ this[0], walk(conditional), walk(t), walk(e) ];
+                },
+                "for": function(init, cond, step, block) {
+                        return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];
+                },
+                "for-in": function(has_var, key, hash, block) {
+                        return [ this[0], has_var, key, walk(hash), walk(block) ];
+                },
+                "while": function(cond, block) {
+                        return [ this[0], walk(cond), walk(block) ];
+                },
+                "do": function(cond, block) {
+                        return [ this[0], walk(cond), walk(block) ];
+                },
+                "return": function(expr) {
+                        return [ this[0], walk(expr) ];
+                },
+                "binary": function(op, left, right) {
+                        return [ this[0], op, walk(left), walk(right) ];
+                },
+                "unary-prefix": function(op, expr) {
+                        return [ this[0], op, walk(expr) ];
+                },
+                "unary-postfix": function(op, expr) {
+                        return [ this[0], op, walk(expr) ];
+                },
+                "sub": function(expr, subscript) {
+                        return [ this[0], walk(expr), walk(subscript) ];
+                },
+                "object": function(props) {
+                        return [ this[0], MAP(props, function(p){
+                                return p.length == 2
+                                        ? [ p[0], walk(p[1]) ]
+                                        : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
+                        }) ];
+                },
+                "regexp": function(rx, mods) {
+                        return [ this[0], rx, mods ];
+                },
+                "array": function(elements) {
+                        return [ this[0], MAP(elements, walk) ];
+                },
+                "stat": function(stat) {
+                        return [ this[0], walk(stat) ];
+                },
+                "seq": function() {
+                        return [ this[0] ].concat(MAP(slice(arguments), walk));
+                },
+                "label": function(name, block) {
+                        return [ this[0], name, walk(block) ];
+                },
+                "with": function(expr, block) {
+                        return [ this[0], walk(expr), walk(block) ];
+                },
+                "atom": function(name) {
+                        return [ this[0], name ];
+                }
+        };
+
+        var user = {};
+        var stack = [];
+        function walk(ast) {
+                if (ast == null)
+                        return null;
+                try {
+                        stack.push(ast);
+                        var type = ast[0];
+                        var gen = user[type];
+                        if (gen) {
+                                var ret = gen.apply(ast, ast.slice(1));
+                                if (ret != null)
+                                        return ret;
+                        }
+                        gen = walkers[type];
+                        return gen.apply(ast, ast.slice(1));
+                } finally {
+                        stack.pop();
+                }
+        };
+
+        function with_walkers(walkers, cont){
+                var save = {}, i;
+                for (i in walkers) if (HOP(walkers, i)) {
+                        save[i] = user[i];
+                        user[i] = walkers[i];
+                }
+                var ret = cont();
+                for (i in save) if (HOP(save, i)) {
+                        if (!save[i]) delete user[i];
+                        else user[i] = save[i];
+                }
+                return ret;
+        };
+
+        return {
+                walk: walk,
+                with_walkers: with_walkers,
+                parent: function() {
+                        return stack[stack.length - 2]; // last one is current node
+                },
+                stack: function() {
+                        return stack;
+                }
+        };
+};
+
+/* -----[ Scope and mangling ]----- */
+
+function Scope(parent) {
+        this.names = {};        // names defined in this scope
+        this.mangled = {};      // mangled names (orig.name => mangled)
+        this.rev_mangled = {};  // reverse lookup (mangled => orig.name)
+        this.cname = -1;        // current mangled name
+        this.refs = {};         // names referenced from this scope
+        this.uses_with = false; // will become TRUE if eval() is detected in this or any subscopes
+        this.uses_eval = false; // will become TRUE if with() is detected in this or any subscopes
+        this.parent = parent;   // parent scope
+        this.children = [];     // sub-scopes
+        if (parent) {
+                this.level = parent.level + 1;
+                parent.children.push(this);
+        } else {
+                this.level = 0;
+        }
+};
+
+var base54 = (function(){
+        var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
+        return function(num) {
+                var ret = "";
+                do {
+                        ret = DIGITS.charAt(num % 54) + ret;
+                        num = Math.floor(num / 54);
+                } while (num > 0);
+                return ret;
+        };
+})();
+
+Scope.prototype = {
+        has: function(name) {
+                for (var s = this; s; s = s.parent)
+                        if (HOP(s.names, name))
+                                return s;
+        },
+        has_mangled: function(mname) {
+                for (var s = this; s; s = s.parent)
+                        if (HOP(s.rev_mangled, mname))
+                                return s;
+        },
+        toJSON: function() {
+                return {
+                        names: this.names,
+                        uses_eval: this.uses_eval,
+                        uses_with: this.uses_with
+                };
+        },
+
+        next_mangled: function() {
+                // we must be careful that the new mangled name:
+                //
+                // 1. doesn't shadow a mangled name from a parent
+                //    scope, unless we don't reference the original
+                //    name from this scope OR from any sub-scopes!
+                //    This will get slow.
+                //
+                // 2. doesn't shadow an original name from a parent
+                //    scope, in the event that the name is not mangled
+                //    in the parent scope and we reference that name
+                //    here OR IN ANY SUBSCOPES!
+                //
+                // 3. doesn't shadow a name that is referenced but not
+                //    defined (possibly global defined elsewhere).
+                for (;;) {
+                        var m = base54(++this.cname), prior;
+
+                        // case 1.
+                        prior = this.has_mangled(m);
+                        if (prior && this.refs[prior.rev_mangled[m]] === prior)
+                                continue;
+
+                        // case 2.
+                        prior = this.has(m);
+                        if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))
+                                continue;
+
+                        // case 3.
+                        if (HOP(this.refs, m) && this.refs[m] == null)
+                                continue;
+
+                        // I got "do" once. :-/
+                        if (!is_identifier(m))
+                                continue;
+
+                        return m;
+                }
+        },
+        get_mangled: function(name, newMangle) {
+                if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use
+                var s = this.has(name);
+                if (!s) return name; // not in visible scope, no mangle
+                if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope
+                if (!newMangle) return name;                      // not found and no mangling requested
+
+                var m = s.next_mangled();
+                s.rev_mangled[m] = name;
+                return s.mangled[name] = m;
+        },
+        define: function(name) {
+                if (name != null)
+                        return this.names[name] = name;
+        }
+};
+
+function ast_add_scope(ast) {
+
+        var current_scope = null;
+        var w = ast_walker(), walk = w.walk;
+        var having_eval = [];
+
+        function with_new_scope(cont) {
+                current_scope = new Scope(current_scope);
+                var ret = current_scope.body = cont();
+                ret.scope = current_scope;
+                current_scope = current_scope.parent;
+                return ret;
+        };
+
+        function define(name) {
+                return current_scope.define(name);
+        };
+
+        function reference(name) {
+                current_scope.refs[name] = true;
+        };
+
+        function _lambda(name, args, body) {
+                return [ this[0], define(name), args, with_new_scope(function(){
+                        MAP(args, define);
+                        return MAP(body, walk);
+                })];
+        };
+
+        return with_new_scope(function(){
+                // process AST
+                var ret = w.with_walkers({
+                        "function": _lambda,
+                        "defun": _lambda,
+                        "with": function(expr, block) {
+                                for (var s = current_scope; s; s = s.parent)
+                                        s.uses_with = true;
+                        },
+                        "var": function(defs) {
+                                MAP(defs, function(d){ define(d[0]) });
+                        },
+                        "const": function(defs) {
+                                MAP(defs, function(d){ define(d[0]) });
+                        },
+                        "try": function(t, c, f) {
+                                if (c != null) return [
+                                        this[0],
+                                        MAP(t, walk),
+                                        [ define(c[0]), MAP(c[1], walk) ],
+                                        f != null ? MAP(f, walk) : null
+                                ];
+                        },
+                        "name": function(name) {
+                                if (name == "eval")
+                                        having_eval.push(current_scope);
+                                reference(name);
+                        },
+                        "for-in": function(has_var, name) {
+                                if (has_var) define(name);
+                                else reference(name);
+                        }
+                }, function(){
+                        return walk(ast);
+                });
+
+                // the reason why we need an additional pass here is
+                // that names can be used prior to their definition.
+
+                // scopes where eval was detected and their parents
+                // are marked with uses_eval, unless they define the
+                // "eval" name.
+                MAP(having_eval, function(scope){
+                        if (!scope.has("eval")) while (scope) {
+                                scope.uses_eval = true;
+                                scope = scope.parent;
+                        }
+                });
+
+                // for referenced names it might be useful to know
+                // their origin scope.  current_scope here is the
+                // toplevel one.
+                function fixrefs(scope, i) {
+                        // do children first; order shouldn't matter
+                        for (i = scope.children.length; --i >= 0;)
+                                fixrefs(scope.children[i]);
+                        for (i in scope.refs) if (HOP(scope.refs, i)) {
+                                // find origin scope and propagate the reference to origin
+                                for (var origin = scope.has(i), s = scope; s; s = s.parent) {
+                                        s.refs[i] = origin;
+                                        if (s === origin) break;
+                                }
+                        }
+                };
+                fixrefs(current_scope);
+
+                return ret;
+        });
+
+};
+
+/* -----[ mangle names ]----- */
+
+function ast_mangle(ast, do_toplevel) {
+        var w = ast_walker(), walk = w.walk, scope;
+
+        function get_mangled(name, newMangle) {
+                if (!do_toplevel && !scope.parent) return name; // don't mangle toplevel
+                return scope.get_mangled(name, newMangle);
+        };
+
+        function _lambda(name, args, body) {
+                if (name) name = get_mangled(name);
+                body = with_scope(body.scope, function(){
+                        args = MAP(args, function(name){ return get_mangled(name) });
+                        return MAP(body, walk);
+                });
+                return [ this[0], name, args, body ];
+        };
+
+        function with_scope(s, cont) {
+                var _scope = scope;
+                scope = s;
+                for (var i in s.names) if (HOP(s.names, i)) {
+                        get_mangled(i, true);
+                }
+                var ret = cont();
+                ret.scope = s;
+                scope = _scope;
+                return ret;
+        };
+
+        function _vardefs(defs) {
+                return [ this[0], MAP(defs, function(d){
+                        return [ get_mangled(d[0]), walk(d[1]) ];
+                }) ];
+        };
+
+        return w.with_walkers({
+                "function": _lambda,
+                "defun": function() {
+                        // move function declarations to the top when
+                        // they are not in some block.
+                        var ast = _lambda.apply(this, arguments);
+                        switch (w.parent()[0]) {
+                            case "toplevel":
+                            case "function":
+                            case "defun":
+                                return MAP.at_top(ast);
+                        }
+                        return ast;
+                },
+                "var": _vardefs,
+                "const": _vardefs,
+                "name": function(name) {
+                        return [ this[0], get_mangled(name) ];
+                },
+                "try": function(t, c, f) {
+                        return [ this[0],
+                                 MAP(t, walk),
+                                 c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
+                                 f != null ? MAP(f, walk) : null ];
+                },
+                "toplevel": function(body) {
+                        var self = this;
+                        return with_scope(self.scope, function(){
+                                return [ self[0], MAP(body, walk) ];
+                        });
+                },
+                "for-in": function(has_var, name, obj, stat) {
+                        return [ this[0], has_var, get_mangled(name), walk(obj), walk(stat) ];
+                }
+        }, function() {
+                return walk(ast_add_scope(ast));
+        });
+};
+
+/* -----[
+   - compress foo["bar"] into foo.bar,
+   - remove block brackets {} where possible
+   - join consecutive var declarations
+   - various optimizations for IFs:
+     - if (cond) foo(); else bar();  ==>  cond?foo():bar();
+     - if (cond) foo();  ==>  cond&&foo();
+     - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw
+     - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}
+   ]----- */
+
+var warn = function(){};
+
+function best_of(ast1, ast2) {
+        return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
+};
+
+function last_stat(b) {
+        if (b[0] == "block" && b[1] && b[1].length > 0)
+                return b[1][b[1].length - 1];
+        return b;
+}
+
+function aborts(t) {
+        if (t) {
+                t = last_stat(t);
+                if (t[0] == "return" || t[0] == "break" || t[0] == "continue" || t[0] == "throw")
+                        return true;
+        }
+};
+
+function boolean_expr(expr) {
+        return ( (expr[0] == "unary-prefix"
+                  && member(expr[1], [ "!", "delete" ])) ||
+
+                 (expr[0] == "binary"
+                  && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) ||
+
+                 (expr[0] == "binary"
+                  && member(expr[1], [ "&&", "||" ])
+                  && boolean_expr(expr[2])
+                  && boolean_expr(expr[3])) ||
+
+                 (expr[0] == "conditional"
+                  && boolean_expr(expr[2])
+                  && boolean_expr(expr[3])) ||
+
+                 (expr[0] == "assign"
+                  && expr[1] === true
+                  && boolean_expr(expr[3])) ||
+
+                 (expr[0] == "seq"
+                  && boolean_expr(expr[expr.length - 1]))
+               );
+};
+
+function make_conditional(c, t, e) {
+        if (c[0] == "unary-prefix" && c[1] == "!") {
+                return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
+        } else {
+                return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
+        }
+};
+
+function empty(b) {
+        return !b || (b[0] == "block" && (!b[1] || b[1].length == 0));
+};
+
+function ast_squeeze(ast, options) {
+        options = defaults(options, {
+                make_seqs   : true,
+                dead_code   : true,
+                keep_comps  : true,
+                no_warnings : false
+        });
+
+        var w = ast_walker(), walk = w.walk, scope;
+
+        function negate(c) {
+                    var not_c = [ "unary-prefix", "!", c ];
+                switch (c[0]) {
+                    case "unary-prefix":
+                        return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c;
+                    case "seq":
+                        c = slice(c);
+                        c[c.length - 1] = negate(c[c.length - 1]);
+                        return c;
+                    case "conditional":
+                        return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]);
+                    case "binary":
+                        var op = c[1], left = c[2], right = c[3];
+                        if (!options.keep_comps) switch (op) {
+                            case "<="  : return [ "binary", ">", left, right ];
+                            case "<"   : return [ "binary", ">=", left, right ];
+                            case ">="  : return [ "binary", "<", left, right ];
+                            case ">"   : return [ "binary", "<=", left, right ];
+                        }
+                        switch (op) {
+                            case "=="  : return [ "binary", "!=", left, right ];
+                            case "!="  : return [ "binary", "==", left, right ];
+                            case "===" : return [ "binary", "!==", left, right ];
+                            case "!==" : return [ "binary", "===", left, right ];
+                            case "&&"  : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]);
+                            case "||"  : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]);
+                        }
+                        break;
+                }
+                return not_c;
+        };
+
+        function with_scope(s, cont) {
+                var _scope = scope;
+                scope = s;
+                var ret = cont();
+                ret.scope = s;
+                scope = _scope;
+                return ret;
+        };
+
+        function is_constant(node) {
+                return node[0] == "string" || node[0] == "num";
+        };
+
+        function rmblock(block) {
+                if (block != null && block[0] == "block" && block[1] && block[1].length == 1)
+                        block = block[1][0];
+                return block;
+        };
+
+        function _lambda(name, args, body) {
+                return [ this[0], name, args, with_scope(body.scope, function(){
+                        return tighten(MAP(body, walk), "lambda");
+                }) ];
+        };
+
+        // we get here for blocks that have been already transformed.
+        // this function does a few things:
+        // 1. discard useless blocks
+        // 2. join consecutive var declarations
+        // 3. remove obviously dead code
+        // 4. transform consecutive statements using the comma operator
+        // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }
+        function tighten(statements, block_type) {
+                statements = statements.reduce(function(a, stat){
+                        if (stat[0] == "block") {
+                                if (stat[1]) {
+                                        a.push.apply(a, stat[1]);
+                                }
+                        } else {
+                                a.push(stat);
+                        }
+                        return a;
+                }, []);
+
+                statements = (function(a, prev){
+                        statements.forEach(function(cur){
+                                if (prev && ((cur[0] == "var" && prev[0] == "var") ||
+                                             (cur[0] == "const" && prev[0] == "const"))) {
+                                        prev[1] = prev[1].concat(cur[1]);
+                                } else {
+                                        a.push(cur);
+                                        prev = cur;
+                                }
+                        });
+                        return a;
+                })([]);
+
+                if (options.dead_code) statements = (function(a, has_quit){
+                        statements.forEach(function(st){
+                                if (has_quit) {
+                                        if (member(st[0], [ "function", "defun" , "var", "const" ])) {
+                                                a.push(st);
+                                        }
+                                        else if (!options.no_warnings)
+                                                warn("Removing unreachable code: " + gen_code(st, true));
+                                }
+                                else {
+                                        a.push(st);
+                                        if (member(st[0], [ "return", "throw", "break", "continue" ]))
+                                                has_quit = true;
+                                }
+                        });
+                        return a;
+                })([]);
+
+                if (options.make_seqs) statements = (function(a, prev) {
+                        statements.forEach(function(cur){
+                                if (prev && prev[0] == "stat" && cur[0] == "stat") {
+                                        prev[1] = [ "seq", prev[1], cur[1] ];
+                                } else {
+                                        a.push(cur);
+                                        prev = cur;
+                                }
+                        });
+                        return a;
+                })([]);
+
+                if (block_type == "lambda") statements = (function(i, a, stat){
+                        while (i < statements.length) {
+                                stat = statements[i++];
+                                if (stat[0] == "if" && !stat[3]) {
+                                        if (stat[2][0] == "return" && stat[2][1] == null) {
+                                                a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ]));
+                                                break;
+                                        }
+                                        var last = last_stat(stat[2]);
+                                        if (last[0] == "return" && last[1] == null) {
+                                                a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ]));
+                                                break;
+                                        }
+                                }
+                                a.push(stat);
+                        }
+                        return a;
+                })(0, []);
+
+                return statements;
+        };
+
+        function make_if(c, t, e) {
+                c = walk(c);
+                t = walk(t);
+                e = walk(e);
+
+                if (empty(t)) {
+                        c = negate(c);
+                        t = e;
+                        e = null;
+                } else if (empty(e)) {
+                        e = null;
+                } else {
+                        // if we have both else and then, maybe it makes sense to switch them?
+                        (function(){
+                                var a = gen_code(c);
+                                var n = negate(c);
+                                var b = gen_code(n);
+                                if (b.length < a.length) {
+                                        var tmp = t;
+                                        t = e;
+                                        e = tmp;
+                                        c = n;
+                                }
+                        })();
+                }
+                if (empty(e) && empty(t))
+                        return [ "stat", c ];
+                var ret = [ "if", c, t, e ];
+                if (t[0] == "if" && empty(t[3]) && empty(e)) {
+                        ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ]));
+                }
+                else if (t[0] == "stat") {
+                        if (e) {
+                                if (e[0] == "stat") {
+                                        ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
+                                }
+                        }
+                        else {
+                                ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
+                        }
+                }
+                else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw")) {
+                        ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);
+                }
+                else if (e && aborts(t)) {
+                        ret = [ [ "if", c, t ] ];
+                        if (e[0] == "block") {
+                                if (e[1]) ret = ret.concat(e[1]);
+                        }
+                        else {
+                                ret.push(e);
+                        }
+                        ret = walk([ "block", ret ]);
+                }
+                else if (t && aborts(e)) {
+                        ret = [ [ "if", negate(c), e ] ];
+                        if (t[0] == "block") {
+                                if (t[1]) ret = ret.concat(t[1]);
+                        } else {
+                                ret.push(t);
+                        }
+                        ret = walk([ "block", ret ]);
+                }
+                return ret;
+        };
+
+        return w.with_walkers({
+                "sub": function(expr, subscript) {
+                        if (subscript[0] == "string") {
+                                var name = subscript[1];
+                                if (is_identifier(name)) {
+                                        return [ "dot", walk(expr), name ];
+                                }
+                        }
+                },
+                "if": make_if,
+                "toplevel": function(body) {
+                        return [ "toplevel", with_scope(this.scope, function(){
+                                return tighten(MAP(body, walk));
+                        }) ];
+                },
+                "switch": function(expr, body) {
+                        var last = body.length - 1;
+                        return [ "switch", walk(expr), MAP(body, function(branch, i){
+                                var block = tighten(MAP(branch[1], walk));
+                                if (i == last && block.length > 0) {
+                                        var node = block[block.length - 1];
+                                        if (node[0] == "break" && !node[1])
+                                                block.pop();
+                                }
+                                return [ branch[0] ? walk(branch[0]) : null, block ];
+                        }) ];
+                },
+                "function": _lambda,
+                "defun": _lambda,
+                "block": function(body) {
+                        if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
+                },
+                "binary": function(op, left, right) {
+                        left = walk(left);
+                        right = walk(right);
+                        var best = [ "binary", op, left, right ];
+                        if (is_constant(right) && is_constant(left)) {
+                                var val = {};
+                                var orig = val;
+                                switch (op) {
+                                    case "+"   : val = left[1] +   right[1]; break;
+                                    case "*"   : val = left[1] *   right[1]; break;
+                                    case "/"   : val = left[1] /   right[1]; break;
+                                    case "-"   : val = left[1] -   right[1]; break;
+                                    case "<<"  : val = left[1] <<  right[1]; break;
+                                    case ">>"  : val = left[1] >>  right[1]; break;
+                                    case ">>>" : val = left[1] >>> right[1]; break;
+                                    case "=="  : val = left[1] ==  right[1]; break;
+                                    case "===" : val = left[1] === right[1]; break;
+                                    case "!="  : val = left[1] !=  right[1]; break;
+                                    case "!==" : val = left[1] !== right[1]; break;
+                                    case "<"   : val = left[1] <   right[1]; break;
+                                    case "<="  : val = left[1] <=  right[1]; break;
+                                    case ">"   : val = left[1] >   right[1]; break;
+                                    case ">="  : val = left[1] >=  right[1]; break;
+                                }
+                                if (val !== orig) {
+                                        switch (typeof val) {
+                                            case "string": val = [ "string", val ]; break;
+                                            case "boolean": val = [ "name", val+"" ]; break;
+                                            case "number": val = [ "num", val ]; break;
+                                            default: return best;
+                                        }
+                                        best = best_of(best, walk(val));
+                                }
+                        }
+                        return best;
+                },
+                "conditional": function(c, t, e) {
+                        return make_conditional(walk(c), walk(t), walk(e));
+                },
+                "try": function(t, c, f) {
+                        return [
+                                "try",
+                                tighten(MAP(t, walk)),
+                                c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null,
+                                f != null ? tighten(MAP(f, walk)) : null
+                        ];
+                },
+                "unary-prefix": function(op, expr) {
+                        expr = walk(expr);
+                        var ret = [ "unary-prefix", op, expr ];
+                        if (op == "!")
+                                ret = best_of(ret, negate(expr));
+                        return ret;
+                },
+                "name": function(name) {
+                        switch (name) {
+                            case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
+                            case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
+                        }
+                },
+                "new": function(ctor, args) {
+                        if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) {
+                                if (args.length != 1) {
+                                        return [ "array", args ];
+                                } else {
+                                        return [ "call", [ "name", "Array" ], args ];
+                                }
+                        }
+                },
+                "call": function(expr, args) {
+                        if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
+                                return [ "array", args ];
+                        }
+                }
+        }, function() {
+                return walk(ast_add_scope(ast));
+        });
+};
+
+/* -----[ re-generate code from the AST ]----- */
+
+var DOT_CALL_NO_PARENS = jsp.array_to_hash([
+        "name",
+        "array",
+        "string",
+        "dot",
+        "sub",
+        "call",
+        "regexp"
+]);
+
+function make_string(str) {
+        var dq = 0, sq = 0;
+        str = str.replace(/[\\\b\f\n\r\t\x22\x27]/g, function(s){
+                switch (s) {
+                    case "\\": return "\\\\";
+                    case "\b": return "\\b";
+                    case "\f": return "\\f";
+                    case "\n": return "\\n";
+                    case "\r": return "\\r";
+                    case "\t": return "\\t";
+                    case '"': ++dq; return '"';
+                    case "'": ++sq; return "'";
+                }
+                return s;
+        });
+        if (dq > sq) {
+                return "'" + str.replace(/\x27/g, "\\'") + "'";
+        } else {
+                return '"' + str.replace(/\x22/g, '\\"') + '"';
+        }
+};
+
+function gen_code(ast, beautify) {
+        if (beautify) beautify = defaults(beautify, {
+                indent_start : 0,
+                indent_level : 4,
+                quote_keys   : false,
+                space_colon  : false
+        });
+        var indentation = 0,
+            newline = beautify ? "\n" : "",
+            space = beautify ? " " : "";
+
+        function indent(line) {
+                if (line == null)
+                        line = "";
+                if (beautify)
+                        line = repeat_string(" ", beautify.indent_start + indentation * beautify.indent_level) + line;
+                return line;
+        };
+
+        function with_indent(cont, incr) {
+                if (incr == null) incr = 1;
+                indentation += incr;
+                try { return cont.apply(null, slice(arguments, 1)); }
+                finally { indentation -= incr; }
+        };
+
+        function add_spaces(a) {
+                if (beautify)
+                        return a.join(" ");
+                var b = [];
+                for (var i = 0; i < a.length; ++i) {
+                        var next = a[i + 1];
+                        b.push(a[i]);
+                        if (next &&
+                            ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) ||
+                             (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) {
+                                b.push(" ");
+                        }
+                }
+                return b.join("");
+        };
+
+        function add_commas(a) {
+                return a.join("," + space);
+        };
+
+        function parenthesize(expr) {
+                var gen = make(expr);
+                for (var i = 1; i < arguments.length; ++i) {
+                        var el = arguments[i];
+                        if ((el instanceof Function && el(expr)) || expr[0] == el)
+                                return "(" + gen + ")";
+                }
+                return gen;
+        };
+
+        function best_of(a) {
+                if (a.length == 1) {
+                        return a[0];
+                }
+                if (a.length == 2) {
+                        var b = a[1];
+                        a = a[0];
+                        return a.length <= b.length ? a : b;
+                }
+                return best_of([ a[0], best_of(a.slice(1)) ]);
+        };
+
+        function needs_parens(expr) {
+                if (expr[0] == "function") {
+                        // dot/call on a literal function requires the
+                        // function literal itself to be parenthesized
+                        // only if it's the first "thing" in a
+                        // statement.  This means that the parent is
+                        // "stat", but it could also be a "seq" and
+                        // we're the first in this "seq" and the
+                        // parent is "stat", and so on.  Messy stuff,
+                        // but it worths the trouble.
+                        var a = slice($stack), self = a.pop(), p = a.pop();
+                        while (p) {
+                                if (p[0] == "stat") return true;
+                                if ((p[0] == "seq" && p[1] === self) ||
+                                    (p[0] == "call" && p[1] === self) ||
+                                    (p[0] == "binary" && p[2] === self)) {
+                                        self = p;
+                                        p = a.pop();
+                                } else {
+                                        return false;
+                                }
+                        }
+                }
+                return !HOP(DOT_CALL_NO_PARENS, expr[0]);
+        };
+
+        function make_num(num) {
+                var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m;
+                if (Math.floor(num) === num) {
+                        a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
+                               "0" + num.toString(8)); // same.
+                        if ((m = /^(.*?)(0+)$/.exec(num))) {
+                                a.push(m[1] + "e" + m[2].length);
+                        }
+                } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
+                        a.push(m[2] + "e-" + (m[1].length + m[2].length),
+                               str.substr(str.indexOf(".")));
+                }
+                return best_of(a);
+        };
+
+        var generators = {
+                "string": make_string,
+                "num": make_num,
+                "name": make_name,
+                "toplevel": function(statements) {
+                        return make_block_statements(statements)
+                                .join(newline + newline);
+                },
+                "block": make_block,
+                "var": function(defs) {
+                        return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
+                },
+                "const": function(defs) {
+                        return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
+                },
+                "try": function(tr, ca, fi) {
+                        var out = [ "try", make_block(tr) ];
+                        if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1]));
+                        if (fi) out.push("finally", make_block(fi));
+                        return add_spaces(out);
+                },
+                "throw": function(expr) {
+                        return add_spaces([ "throw", make(expr) ]) + ";";
+                },
+                "new": function(ctor, args) {
+                        args = args.length > 0 ? "(" + add_commas(MAP(args, make)) + ")" : "";
+                        return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
+                                var w = ast_walker(), has_call = {};
+                                try {
+                                        w.with_walkers({
+                                                "call": function() { throw has_call },
+                                                "function": function() { return this }
+                                        }, function(){
+                                                w.walk(expr);
+                                        });
+                                } catch(ex) {
+                                        if (ex === has_call)
+                                                return true;
+                                        throw ex;
+                                }
+                        }) + args ]);
+                },
+                "switch": function(expr, body) {
+                        return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]);
+                },
+                "break": function(label) {
+                        var out = "break";
+                        if (label != null)
+                                out += " " + make_name(label);
+                        return out + ";";
+                },
+                "continue": function(label) {
+                        var out = "continue";
+                        if (label != null)
+                                out += " " + make_name(label);
+                        return out + ";";
+                },
+                "conditional": function(co, th, el) {
+                        return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?",
+                                            parenthesize(th, "seq"), ":",
+                                            parenthesize(el, "seq") ]);
+                },
+                "assign": function(op, lvalue, rvalue) {
+                        if (op && op !== true) op += "=";
+                        else op = "=";
+                        return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
+                },
+                "dot": function(expr) {
+                        var out = make(expr), i = 1;
+                        if (expr[0] == "num")
+                                out += ".";
+                        else if (needs_parens(expr))
+                                out = "(" + out + ")";
+                        while (i < arguments.length)
+                                out += "." + make_name(arguments[i++]);
+                        return out;
+                },
+                "call": function(func, args) {
+                        var f = make(func);
+                        if (needs_parens(func))
+                                f = "(" + f + ")";
+                        return f + "(" + add_commas(MAP(args, function(expr){
+                                return parenthesize(expr, "seq");
+                        })) + ")";
+                },
+                "function": make_function,
+                "defun": make_function,
+                "if": function(co, th, el) {
+                        var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ];
+                        if (el) {
+                                out.push("else", make(el));
+                        }
+                        return add_spaces(out);
+                },
+                "for": function(init, cond, step, block) {
+                        var out = [ "for" ];
+                        init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space);
+                        cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space);
+                        step = (step != null ? make(step) : "").replace(/;*\s*$/, "");
+                        var args = init + cond + step;
+                        if (args == "; ; ") args = ";;";
+                        out.push("(" + args + ")", make(block));
+                        return add_spaces(out);
+                },
+                "for-in": function(has_var, key, hash, block) {
+                        var out = add_spaces([ "for", "(" ]);
+                        if (has_var)
+                                out += "var ";
+                        out += add_spaces([ make_name(key) + " in " + make(hash) + ")", make(block) ]);
+                        return out;
+                },
+                "while": function(condition, block) {
+                        return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]);
+                },
+                "do": function(condition, block) {
+                        return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";";
+                },
+                "return": function(expr) {
+                        var out = [ "return" ];
+                        if (expr != null) out.push(make(expr));
+                        return add_spaces(out) + ";";
+                },
+                "binary": function(operator, lvalue, rvalue) {
+                        var left = make(lvalue), right = make(rvalue);
+                        // XXX: I'm pretty sure other cases will bite here.
+                        //      we need to be smarter.
+                        //      adding parens all the time is the safest bet.
+                        if (member(lvalue[0], [ "assign", "conditional", "seq" ]) ||
+                            lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]]) {
+                                left = "(" + left + ")";
+                        }
+                        if (member(rvalue[0], [ "assign", "conditional", "seq" ]) ||
+                            rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&
+                            !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) {
+                                right = "(" + right + ")";
+                        }
+                        return add_spaces([ left, operator, right ]);
+                },
+                "unary-prefix": function(operator, expr) {
+                        var val = make(expr);
+                        if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
+                                val = "(" + val + ")";
+                        return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val;
+                },
+                "unary-postfix": function(operator, expr) {
+                        var val = make(expr);
+                        if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
+                                val = "(" + val + ")";
+                        return val + operator;
+                },
+                "sub": function(expr, subscript) {
+                        var hash = make(expr);
+                        if (needs_parens(expr))
+                                hash = "(" + hash + ")";
+                        return hash + "[" + make(subscript) + "]";
+                },
+                "object": function(props) {
+                        if (props.length == 0)
+                                return "{}";
+                        return "{" + newline + with_indent(function(){
+                                return MAP(props, function(p){
+                                        if (p.length == 3) {
+                                                // getter/setter.  The name is in p[0], the arg.list in p[1][2], the
+                                                // body in p[1][3] and type ("get" / "set") in p[2].
+                                                return indent(make_function(p[0], p[1][2], p[1][3], p[2]));
+                                        }
+                                        var key = p[0], val = make(p[1]);
+                                        if (beautify && beautify.quote_keys) {
+                                                key = make_string(key);
+                                        } else if ((typeof key == "number" || !beautify && +key + "" == key)
+                                                   && parseFloat(key) >= 0) {
+                                                key = make_num(+key);
+                                        } else if (!is_identifier(key)) {
+                                                key = make_string(key);
+                                        }
+                                        return indent(add_spaces(beautify && beautify.space_colon
+                                                                 ? [ key, ":", val ]
+                                                                 : [ key + ":", val ]));
+                                }).join("," + newline);
+                        }) + newline + indent("}");
+                },
+                "regexp": function(rx, mods) {
+                        return "/" + rx + "/" + mods;
+                },
+                "array": function(elements) {
+                        if (elements.length == 0) return "[]";
+                        return add_spaces([ "[", add_commas(MAP(elements, function(el){
+                                if (!beautify && el[0] == "atom" && el[1] == "undefined") return "";
+                                return parenthesize(el, "seq");
+                        })), "]" ]);
+                },
+                "stat": function(stmt) {
+                        return make(stmt).replace(/;*\s*$/, ";");
+                },
+                "seq": function() {
+                        return add_commas(MAP(slice(arguments), make));
+                },
+                "label": function(name, block) {
+                        return add_spaces([ make_name(name), ":", make(block) ]);
+                },
+                "with": function(expr, block) {
+                        return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]);
+                },
+                "atom": function(name) {
+                        return make_name(name);
+                }
+        };
+
+        // The squeezer replaces "block"-s that contain only a single
+        // statement with the statement itself; technically, the AST
+        // is correct, but this can create problems when we output an
+        // IF having an ELSE clause where the THEN clause ends in an
+        // IF *without* an ELSE block (then the outer ELSE would refer
+        // to the inner IF).  This function checks for this case and
+        // adds the block brackets if needed.
+        function make_then(th) {
+                if (th[0] == "do") {
+                        // https://github.com/mishoo/UglifyJS/issues/#issue/57
+                        // IE croaks with "syntax error" on code like this:
+                        //     if (foo) do ... while(cond); else ...
+                        // we need block brackets around do/while
+                        return make([ "block", [ th ]]);
+                }
+                var b = th;
+                while (true) {
+                        var type = b[0];
+                        if (type == "if") {
+                                if (!b[3])
+                                        // no else, we must add the block
+                                        return make([ "block", [ th ]]);
+                                b = b[3];
+                        }
+                        else if (type == "while" || type == "do") b = b[2];
+                        else if (type == "for" || type == "for-in") b = b[4];
+                        else break;
+                }
+                return make(th);
+        };
+
+        function make_function(name, args, body, keyword) {
+                var out = keyword || "function";
+                if (name) {
+                        out += " " + make_name(name);
+                }
+                out += "(" + add_commas(MAP(args, make_name)) + ")";
+                return add_spaces([ out, make_block(body) ]);
+        };
+
+        function make_name(name) {
+                return name.toString();
+        };
+
+        function make_block_statements(statements) {
+                for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
+                        var stat = statements[i];
+                        var code = make(stat);
+                        if (code != ";") {
+                                if (!beautify && i == last) {
+                                        if ((stat[0] == "while" && empty(stat[2])) ||
+                                            (member(stat[0], [ "for", "for-in"] ) && empty(stat[4])) ||
+                                            (stat[0] == "if" && empty(stat[2]) && !stat[3]) ||
+                                            (stat[0] == "if" && stat[3] && empty(stat[3]))) {
+                                                code = code.replace(/;*\s*$/, ";");
+                                        } else {
+                                                code = code.replace(/;+\s*$/, "");
+                                        }
+                                }
+                                a.push(code);
+                        }
+                }
+                return MAP(a, indent);
+        };
+
+        function make_switch_block(body) {
+                var n = body.length;
+                if (n == 0) return "{}";
+                return "{" + newline + MAP(body, function(branch, i){
+                        var has_body = branch[1].length > 0, code = with_indent(function(){
+                                return indent(branch[0]
+                                              ? add_spaces([ "case", make(branch[0]) + ":" ])
+                                              : "default:");
+                        }, 0.5) + (has_body ? newline + with_indent(function(){
+                                return make_block_statements(branch[1]).join(newline);
+                        }) : "");
+                        if (!beautify && has_body && i < n - 1)
+                                code += ";";
+                        return code;
+                }).join(newline) + newline + indent("}");
+        };
+
+        function make_block(statements) {
+                if (!statements) return ";";
+                if (statements.length == 0) return "{}";
+                return "{" + newline + with_indent(function(){
+                        return make_block_statements(statements).join(newline);
+                }) + newline + indent("}");
+        };
+
+        function make_1vardef(def) {
+                var name = def[0], val = def[1];
+                if (val != null)
+                        name = add_spaces([ name, "=", make(val) ]);
+                return name;
+        };
+
+        var $stack = [];
+
+        function make(node) {
+                var type = node[0];
+                var gen = generators[type];
+                if (!gen)
+                        throw new Error("Can't find generator for \"" + type + "\"");
+                $stack.push(node);
+                var ret = gen.apply(type, node.slice(1));
+                $stack.pop();
+                return ret;
+        };
+
+        return make(ast);
+};
+
+function split_lines(code, max_line_length) {
+        var splits = [ 0 ];
+        jsp.parse(function(){
+                var next_token = jsp.tokenizer(code);
+                var last_split = 0;
+                var prev_token;
+                function current_length(tok) {
+                        return tok.pos - last_split;
+                };
+                function split_here(tok) {
+                        last_split = tok.pos;
+                        splits.push(last_split);
+                };
+                function custom(){
+                        var tok = next_token.apply(this, arguments);
+                        out: {
+                                if (prev_token) {
+                                        if (prev_token.type == "keyword") break out;
+                                }
+                                if (current_length(tok) > max_line_length) {
+                                        switch (tok.type) {
+                                            case "keyword":
+                                            case "atom":
+                                            case "name":
+                                            case "punc":
+                                                split_here(tok);
+                                                break out;
+                                        }
+                                }
+                        }
+                        prev_token = tok;
+                        return tok;
+                };
+                custom.context = function() {
+                        return next_token.context.apply(this, arguments);
+                };
+                return custom;
+        }());
+        return splits.map(function(pos, i){
+                return code.substring(pos, splits[i + 1] || code.length);
+        }).join("\n");
+};
+
+/* -----[ Utilities ]----- */
+
+function repeat_string(str, i) {
+        if (i <= 0) return "";
+        if (i == 1) return str;
+        var d = repeat_string(str, i >> 1);
+        d += d;
+        if (i & 1) d += str;
+        return d;
+};
+
+function defaults(args, defs) {
+        var ret = {};
+        if (args === true)
+                args = {};
+        for (var i in defs) if (HOP(defs, i)) {
+                ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
+        }
+        return ret;
+};
+
+function is_identifier(name) {
+        return /^[a-z_$][a-z0-9_$]*$/i.test(name)
+                && name != "this"
+                && !HOP(jsp.KEYWORDS_ATOM, name)
+                && !HOP(jsp.RESERVED_WORDS, name)
+                && !HOP(jsp.KEYWORDS, name);
+};
+
+function HOP(obj, prop) {
+        return Object.prototype.hasOwnProperty.call(obj, prop);
+};
+
+// some utilities
+
+var MAP;
+
+(function(){
+        MAP = function(a, f, o) {
+                var ret = [];
+                for (var i = 0; i < a.length; ++i) {
+                        var val = f.call(o, a[i], i);
+                        if (val instanceof AtTop) ret.unshift(val.v);
+                        else ret.push(val);
+                }
+                return ret;
+        };
+        MAP.at_top = function(val) { return new AtTop(val) };
+        function AtTop(val) { this.v = val };
+})();
+
+/* -----[ Exports ]----- */
+
+exports.ast_walker = ast_walker;
+exports.ast_mangle = ast_mangle;
+exports.ast_squeeze = ast_squeeze;
+exports.gen_code = gen_code;
+exports.ast_add_scope = ast_add_scope;
+exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
+exports.set_logger = function(logger) { warn = logger };
+exports.make_string = make_string;
+exports.split_lines = split_lines;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/View.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/View.js
new file mode 100644
index 0000000..632a61a
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/View.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.View = function(element)
+{
+    this.element = element || document.createElement("div");
+    this._visible = false;
+}
+
+WebInspector.View.prototype = {
+    get visible()
+    {
+        return this._visible;
+    },
+
+    set visible(x)
+    {
+        if (this._visible === x)
+            return;
+
+        if (x)
+            this.show();
+        else
+            this.hide();
+    },
+
+    show: function(parentElement)
+    {
+        this._visible = true;
+        if (parentElement && parentElement !== this.element.parentNode) {
+            this.detach();
+            parentElement.appendChild(this.element);
+        }
+        if (!this.element.parentNode && this.attach)
+            this.attach();
+        this.element.addStyleClass("visible");
+    },
+
+    hide: function()
+    {
+        this.element.removeStyleClass("visible");
+        this._visible = false;
+    },
+
+    detach: function()
+    {
+        if (this.element.parentNode)
+            this.element.parentNode.removeChild(this.element);
+    }
+}
+
+WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
new file mode 100644
index 0000000..a6f59ca
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) IBM Corp. 2009  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of IBM Corp. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.WatchExpressionsSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions"));
+    this.reset();
+}
+
+WebInspector.WatchExpressionsSidebarPane.prototype = {
+    reset: function()
+    {
+        this.bodyElement.removeChildren();
+
+        this.expanded = WebInspector.settings.watchExpressions.length > 0;
+        this.section = new WebInspector.WatchExpressionsSection();
+        this.bodyElement.appendChild(this.section.element);
+
+        var addElement = document.createElement("button");
+        addElement.setAttribute("type", "button");
+        addElement.textContent = WebInspector.UIString("Add");
+        addElement.addEventListener("click", this.section.addExpression.bind(this.section), false);
+
+        var refreshElement = document.createElement("button");
+        refreshElement.setAttribute("type", "button");
+        refreshElement.textContent = WebInspector.UIString("Refresh");
+        refreshElement.addEventListener("click", this.section.update.bind(this.section), false);
+
+        var centerElement = document.createElement("div");
+        centerElement.addStyleClass("watch-expressions-buttons-container");
+        centerElement.appendChild(addElement);
+        centerElement.appendChild(refreshElement);
+        this.bodyElement.appendChild(centerElement);
+
+        this.onexpand = this.refreshExpressions.bind(this);
+    },
+
+    refreshExpressions: function()
+    {
+        if (this.section)
+            this.section.update();
+    }
+}
+
+WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.WatchExpressionsSection = function()
+{
+    this._watchObjectGroupId = "watch-group";
+
+    WebInspector.ObjectPropertiesSection.call(this);
+
+    this.watchExpressions = WebInspector.settings.watchExpressions;
+
+    this.headerElement.className = "hidden";
+    this.editable = true;
+    this.expanded = true;
+    this.propertiesElement.addStyleClass("watch-expressions");
+}
+
+WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0";
+
+WebInspector.WatchExpressionsSection.prototype = {
+    update: function()
+    {
+        function appendResult(expression, watchIndex, result)
+        {
+            var property = new WebInspector.RemoteObjectProperty(expression, result);
+            property.watchIndex = watchIndex;
+
+            // To clarify what's going on here: 
+            // In the outer function, we calculate the number of properties
+            // that we're going to be updating, and set that in the
+            // propertyCount variable.  
+            // In this function, we test to see when we are processing the 
+            // last property, and then call the superclass's updateProperties() 
+            // method to get all the properties refreshed at once.
+            properties.push(property);
+            
+            if (properties.length == propertyCount) {
+                this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);
+
+                // check to see if we just added a new watch expression,
+                // which will always be the last property
+                if (this._newExpressionAdded) {
+                    delete this._newExpressionAdded;
+
+                    treeElement = this.findAddedTreeElement();
+                    if (treeElement)
+                        treeElement.startEditing();
+                }
+            }
+        }
+
+        // TODO: pass exact injected script id.
+        InspectorBackend.releaseWrapperObjectGroup(0, this._watchObjectGroupId)
+        var properties = [];
+
+        // Count the properties, so we known when to call this.updateProperties()
+        // in appendResult()
+        var propertyCount = 0;
+        for (var i = 0; i < this.watchExpressions.length; ++i) {
+            if (!this.watchExpressions[i]) 
+                continue;
+            ++propertyCount;
+        }
+
+        // Now process all the expressions, since we have the actual count,
+        // which is checked in the appendResult inner function.
+        for (var i = 0; i < this.watchExpressions.length; ++i) {
+            var expression = this.watchExpressions[i];
+            if (!expression)
+                continue;
+
+            WebInspector.console.evalInInspectedWindow("(" + expression + ")", this._watchObjectGroupId, false, appendResult.bind(this, expression, i));
+        }
+
+        // note this is setting the expansion of the tree, not the section;
+        // with no expressions, and expanded tree, we get some extra vertical
+        // white space
+        // FIXME: should change to use header buttons instead of the buttons
+        // at the bottom of the section, then we can add a "No Watch Expressions
+        // element when there are no watch expressions, and this issue should
+        // go away.
+        this.expanded = (propertyCount != 0);
+    },
+
+    addExpression: function()
+    {
+        this._newExpressionAdded = true;
+        this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression);
+        this.update();
+    },
+
+    updateExpression: function(element, value)
+    {
+        this.watchExpressions[element.property.watchIndex] = value;
+        this.saveExpressions();
+        this.update();
+    },
+
+    findAddedTreeElement: function()
+    {
+        var children = this.propertiesTreeOutline.children;
+        for (var i = 0; i < children.length; ++i)
+            if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
+                return children[i];
+    },
+
+    saveExpressions: function()
+    {
+        var toSave = [];
+        for (var i = 0; i < this.watchExpressions.length; i++)
+            if (this.watchExpressions[i])
+                toSave.push(this.watchExpressions[i]);
+
+        WebInspector.settings.watchExpressions = toSave;
+        return toSave.length;
+    }
+}
+
+WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;
+
+WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB) 
+{
+    if (propertyA.watchIndex == propertyB.watchIndex)
+        return 0;
+    else if (propertyA.watchIndex < propertyB.watchIndex)
+        return -1;
+    else
+        return 1;
+}
+
+WebInspector.WatchExpressionTreeElement = function(property)
+{
+    WebInspector.ObjectPropertyTreeElement.call(this, property);
+}
+
+WebInspector.WatchExpressionTreeElement.prototype = {
+    update: function()
+    {
+        WebInspector.ObjectPropertyTreeElement.prototype.update.call(this);
+
+        if (this.property.value.isError())
+            this.valueElement.addStyleClass("watch-expressions-error-level");
+
+        var deleteButton = document.createElement("input");
+        deleteButton.type = "button";
+        deleteButton.title = WebInspector.UIString("Delete watch expression.");
+        deleteButton.addStyleClass("enabled-button");
+        deleteButton.addStyleClass("delete-button");
+        deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
+
+        this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild);
+    },
+
+    _deleteButtonClicked: function()
+    {
+        this.treeOutline.section.updateExpression(this, null);
+    },
+
+    startEditing: function()
+    {
+        if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable)
+            return;
+
+        this.nameElement.textContent = this.property.name.trim();
+
+        var context = { expanded: this.expanded };
+
+        // collapse temporarily, if required
+        this.hasChildren = false;
+
+        this.listItemElement.addStyleClass("editing-sub-part");
+
+        WebInspector.startEditing(this.nameElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
+    },
+
+    editingCancelled: function(element, context)
+    {
+        if (!this.nameElement.textContent)
+            this.treeOutline.section.updateExpression(this, null);
+            
+        this.update();
+        this.editingEnded(context);
+    },
+
+    applyExpression: function(expression, updateInterface)
+    {
+        expression = expression.trim();
+
+        if (!expression)
+            expression = null;
+
+        this.property.name = expression;
+        this.treeOutline.section.updateExpression(this, expression);
+    }
+}
+
+WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/WebKit.qrc b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WebKit.qrc
new file mode 100644
index 0000000..dd325ba
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WebKit.qrc
@@ -0,0 +1,286 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/webkit/inspector">
+    <file>inspector.html</file>
+    <file>ApplicationCacheItemsView.js</file>
+    <file>AuditCategories.js</file>
+    <file>AuditFormatters.js</file>
+    <file>AuditLauncherView.js</file>
+    <file>AuditResultView.js</file>
+    <file>AuditRules.js</file>
+    <file>AuditsPanel.js</file>
+    <file>BottomUpProfileDataGridTree.js</file>
+    <file>Breakpoint.js</file>
+    <file>BreakpointManager.js</file>
+    <file>BreakpointsSidebarPane.js</file>
+    <file>CallStackSidebarPane.js</file>
+    <file>Checkbox.js</file>
+    <file>Color.js</file>
+    <file>ConsolePanel.js</file>
+    <file>ConsoleView.js</file>
+    <file>ContextMenu.js</file>
+    <file>CookieItemsView.js</file>
+    <file>CookieParser.js</file>
+    <file>CookiesTable.js</file>
+    <file>CSSCompletions.js</file>
+    <file>CSSKeywordCompletions.js</file>
+    <file>CSSStyleModel.js</file>
+    <file>Database.js</file>
+    <file>DatabaseQueryView.js</file>
+    <file>DatabaseTableView.js</file>
+    <file>DetailedHeapshotView.js</file>
+    <file>DataGrid.js</file>
+    <file>DebuggerModel.js</file>
+    <file>DOMAgent.js</file>
+    <file>DOMStorage.js</file>
+    <file>DOMStorageItemsView.js</file>
+    <file>DOMSyntaxHighlighter.js</file>
+    <file>Drawer.js</file>
+    <file>ElementsPanel.js</file>
+    <file>ElementsTreeOutline.js</file>
+    <file>EventListenersSidebarPane.js</file>
+    <file>ExtensionAPI.js</file>
+    <file>ExtensionAuditCategory.js</file>
+    <file>ExtensionCommon.js</file>
+    <file>ExtensionPanel.js</file>
+    <file>ExtensionRegistryStub.js</file>
+    <file>ExtensionServer.js</file>
+    <file>FontView.js</file>
+    <file>GoToLineDialog.js</file>
+    <file>HAREntry.js</file>
+    <file>HeapSnapshot.js</file>
+    <file>HeapSnapshotView.js</file>
+    <file>HelpScreen.js</file>
+    <file>ImageView.js</file>
+    <file>InjectedFakeWorker.js</file>
+    <file>inspector.js</file>
+    <file>InspectorFrontendHostStub.js</file>
+    <file>KeyboardShortcut.js</file>
+    <file>MetricsSidebarPane.js</file>
+    <file>NetworkItemView.js</file>
+    <file>NetworkManager.js</file>
+    <file>NetworkPanel.js</file>
+    <file>Object.js</file>
+    <file>ObjectPropertiesSection.js</file>
+    <file>Panel.js</file>
+    <file>PanelEnablerView.js</file>
+    <file>Placard.js</file>
+    <file>PleaseWaitMessage.js</file>
+    <file>Popover.js</file>
+    <file>ProfileDataGridTree.js</file>
+    <file>ProfilesPanel.js</file>
+    <file>ProfileView.js</file>
+    <file>PropertiesSection.js</file>
+    <file>PropertiesSidebarPane.js</file>
+    <file>RemoteObject.js</file>
+    <file>Resource.js</file>
+    <file>ResourceCategory.js</file>
+    <file>ResourceCookiesView.js</file>
+    <file>ResourceHeadersView.js</file>
+    <file>ResourceTimingView.js</file>
+    <file>ResourceTreeModel.js</file>
+    <file>ResourceView.js</file>
+    <file>ResourcesPanel.js</file>
+    <file>ScopeChainSidebarPane.js</file>
+    <file>Script.js</file>
+    <file>ScriptFormatter.js</file>
+    <file>ScriptFormatterWorker.js</file>
+    <file>ScriptsPanel.js</file>
+    <file>Section.js</file>
+    <file>Settings.js</file>
+    <file>ShortcutsHelp.js</file>
+    <file>ShowMoreDataGridNode.js</file>
+    <file>SidebarPane.js</file>
+    <file>SidebarTreeElement.js</file>
+    <file>SourceCSSTokenizer.js</file>
+    <file>SourceFrame.js</file>
+    <file>SourceFrameContent.js</file>
+    <file>SourceHTMLTokenizer.js</file>
+    <file>SourceJavaScriptTokenizer.js</file>
+    <file>SourceTokenizer.js</file>
+    <file>StatusBarButton.js</file>
+    <file>StylesSidebarPane.js</file>
+    <file>SummaryBar.js</file>
+    <file>TabbedPane.js</file>
+    <file>TestController.js</file>
+    <file>TextEditorHighlighter.js</file>
+    <file>TextEditorModel.js</file>
+    <file>TextPrompt.js</file>
+    <file>TextViewer.js</file>
+    <file>TimelineAgent.js</file>
+    <file>TimelineGrid.js</file>
+    <file>TimelineOverviewPane.js</file>
+    <file>TimelinePanel.js</file>
+    <file>TopDownProfileDataGridTree.js</file>
+    <file>treeoutline.js</file>
+    <file>utilities.js</file>
+    <file>View.js</file>
+    <file>WatchExpressionsSidebarPane.js</file>
+    <file>WelcomeView.js</file>
+    <file>WorkersSidebarPane.js</file>
+    <file>UglifyJS/parse-js.js</file>
+    <file>UglifyJS/process.js</file>
+    <file>audits.css</file>
+    <file>goToLineDialog.css</file>
+    <file>heapProfiler.css</file>
+    <file>helpScreen.css</file>
+    <file>inspector.css</file>
+    <file>inspectorSyntaxHighlight.css</file>
+    <file>networkPanel.css</file>
+    <file>popover.css</file>
+    <file>textViewer.css</file>
+    <file>Images/applicationCache.png</file>
+    <file>Images/auditsIcon.png</file>
+    <file>Images/back.png</file>
+    <file>Images/breakpointBorder.png</file>
+    <file>Images/breakpointConditionalBorder.png</file>
+    <file>Images/breakpointConditionalCounterBorder.png</file>
+    <file>Images/breakpointCounterBorder.png</file>
+    <file>Images/breakpointsActivateButtonGlyph.png</file>
+    <file>Images/breakpointsDeactivateButtonGlyph.png</file>
+    <file>Images/checker.png</file>
+    <file>Images/clearConsoleButtonGlyph.png</file>
+    <file>Images/closeButtons.png</file>
+    <file>Images/consoleButtonGlyph.png</file>
+    <file>Images/cookie.png</file>
+    <file>Images/consoleIcon.png</file>
+    <file>Images/database.png</file>
+    <file>Images/databaseTable.png</file>
+    <file>Images/debuggerContinue.png</file>
+    <file>Images/debuggerPause.png</file>
+    <file>Images/debuggerStepInto.png</file>
+    <file>Images/debuggerStepOut.png</file>
+    <file>Images/debuggerStepOver.png</file>
+    <file>Images/disclosureTriangleSmallDown.png</file>
+    <file>Images/disclosureTriangleSmallDownBlack.png</file>
+    <file>Images/disclosureTriangleSmallDownWhite.png</file>
+    <file>Images/disclosureTriangleSmallRight.png</file>
+    <file>Images/disclosureTriangleSmallRightBlack.png</file>
+    <file>Images/disclosureTriangleSmallRightDown.png</file>
+    <file>Images/disclosureTriangleSmallRightDownBlack.png</file>
+    <file>Images/disclosureTriangleSmallRightDownWhite.png</file>
+    <file>Images/disclosureTriangleSmallRightWhite.png</file>
+    <file>Images/dockButtonGlyph.png</file>
+    <file>Images/elementsIcon.png</file>
+    <file>Images/enableOutlineButtonGlyph.png</file>
+    <file>Images/enableSolidButtonGlyph.png</file>
+    <file>Images/errorIcon.png</file>
+    <file>Images/errorMediumIcon.png</file>
+    <file>Images/errorRedDot.png</file>
+    <file>Images/excludeButtonGlyph.png</file>
+    <file>Images/focusButtonGlyph.png</file>
+    <file>Images/forward.png</file>
+    <file>Images/frame.png</file>
+    <file>Images/gearButtonGlyph.png</file>
+    <file>Images/glossyHeader.png</file>
+    <file>Images/glossyHeaderPressed.png</file>
+    <file>Images/glossyHeaderSelected.png</file>
+    <file>Images/glossyHeaderSelectedPressed.png</file>
+    <file>Images/goArrow.png</file>
+    <file>Images/graphLabelCalloutLeft.png</file>
+    <file>Images/graphLabelCalloutRight.png</file>
+    <file>Images/largerResourcesButtonGlyph.png</file>
+    <file>Images/localStorage.png</file>
+    <file>Images/networkIcon.png</file>
+    <file>Images/nodeSearchButtonGlyph.png</file>
+    <file>Images/paneAddButtons.png</file>
+    <file>Images/paneBottomGrow.png</file>
+    <file>Images/paneBottomGrowActive.png</file>
+    <file>Images/paneGrowHandleLine.png</file>
+    <file>Images/paneSettingsButtons.png</file>
+    <file>Images/pauseOnExceptionButtonGlyph.png</file>
+    <file>Images/percentButtonGlyph.png</file>
+    <file>Images/popoverArrows.png</file>
+    <file>Images/popoverBackground.png</file>
+    <file>Images/profileGroupIcon.png</file>
+    <file>Images/profileIcon.png</file>
+    <file>Images/profilesIcon.png</file>
+    <file>Images/profileSmallIcon.png</file>
+    <file>Images/profilesSilhouette.png</file>
+    <file>Images/programCounterBorder.png</file>
+    <file>Images/radioDot.png</file>
+    <file>Images/recordButtonGlyph.png</file>
+    <file>Images/recordToggledButtonGlyph.png</file>
+    <file>Images/reloadButtonGlyph.png</file>
+    <file>Images/resourceCSSIcon.png</file>
+    <file>Images/resourceDocumentIcon.png</file>
+    <file>Images/resourceDocumentIconSmall.png</file>
+    <file>Images/resourceJSIcon.png</file>
+    <file>Images/resourcePlainIcon.png</file>
+    <file>Images/resourcePlainIconSmall.png</file>
+    <file>Images/resourcesIcon.png</file>
+    <file>Images/resourcesSizeGraphIcon.png</file>
+    <file>Images/resourcesTimeGraphIcon.png</file>
+    <file>Images/scriptsIcon.png</file>
+    <file>Images/scriptsSilhouette.png</file>
+    <file>Images/searchSmallBlue.png</file>
+    <file>Images/searchSmallBrightBlue.png</file>
+    <file>Images/searchSmallGray.png</file>
+    <file>Images/searchSmallWhite.png</file>
+    <file>Images/segment.png</file>
+    <file>Images/segmentEnd.png</file>
+    <file>Images/segmentHover.png</file>
+    <file>Images/segmentHoverEnd.png</file>
+    <file>Images/segmentSelected.png</file>
+    <file>Images/segmentSelectedEnd.png</file>
+    <file>Images/sessionStorage.png</file>
+    <file>Images/spinner.gif</file>
+    <file>Images/splitviewDimple.png</file>
+    <file>Images/splitviewDividerBackground.png</file>
+    <file>Images/statusbarBackground.png</file>
+    <file>Images/statusbarBottomBackground.png</file>
+    <file>Images/statusbarButtons.png</file>
+    <file>Images/statusbarMenuButton.png</file>
+    <file>Images/statusbarMenuButtonSelected.png</file>
+    <file>Images/statusbarResizerHorizontal.png</file>
+    <file>Images/statusbarResizerVertical.png</file>
+    <file>Images/successGreenDot.png</file>
+    <file>Images/thumbActiveHoriz.png</file>
+    <file>Images/thumbActiveVert.png</file>
+    <file>Images/thumbHoriz.png</file>
+    <file>Images/thumbVert.png</file>
+    <file>Images/thumbHoverHoriz.png</file>
+    <file>Images/thumbHoverVert.png</file>
+    <file>Images/timelineBarBlue.png</file>
+    <file>Images/timelineBarGray.png</file>
+    <file>Images/timelineBarGreen.png</file>
+    <file>Images/timelineBarOrange.png</file>
+    <file>Images/timelineBarPurple.png</file>
+    <file>Images/timelineBarRed.png</file>
+    <file>Images/timelineBarYellow.png</file>
+    <file>Images/timelineCheckmarks.png</file>
+    <file>Images/timelineDots.png</file>
+    <file>Images/timelineHollowPillBlue.png</file>
+    <file>Images/timelineHollowPillGray.png</file>
+    <file>Images/timelineHollowPillGreen.png</file>
+    <file>Images/timelineHollowPillOrange.png</file>
+    <file>Images/timelineHollowPillPurple.png</file>
+    <file>Images/timelineHollowPillRed.png</file>
+    <file>Images/timelineHollowPillYellow.png</file>
+    <file>Images/timelineIcon.png</file>
+    <file>Images/timelinePillBlue.png</file>
+    <file>Images/timelinePillGray.png</file>
+    <file>Images/timelinePillGreen.png</file>
+    <file>Images/timelinePillOrange.png</file>
+    <file>Images/timelinePillPurple.png</file>
+    <file>Images/timelinePillRed.png</file>
+    <file>Images/timelinePillYellow.png</file>
+    <file>Images/toolbarItemSelected.png</file>
+    <file>Images/trackHoriz.png</file>
+    <file>Images/trackVert.png</file>
+    <file>Images/treeDownTriangleBlack.png</file>
+    <file>Images/treeDownTriangleWhite.png</file>
+    <file>Images/treeRightTriangleBlack.png</file>
+    <file>Images/treeRightTriangleWhite.png</file>
+    <file>Images/treeUpTriangleBlack.png</file>
+    <file>Images/treeUpTriangleWhite.png</file>
+    <file>Images/undockButtonGlyph.png</file>
+    <file>Images/userInputIcon.png</file>
+    <file>Images/userInputPreviousIcon.png</file>
+    <file>Images/userInputResultIcon.png</file>
+    <file>Images/warningIcon.png</file>
+    <file>Images/warningMediumIcon.png</file>
+    <file>Images/warningOrangeDot.png</file>
+    <file>Images/warningsErrors.png</file>
+    <file alias="DebuggerScript.js">../../bindings/v8/DebuggerScript.js</file>
+</qresource>
+</RCC>
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/WelcomeView.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WelcomeView.js
new file mode 100644
index 0000000..0feee12
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WelcomeView.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.WelcomeView = function(identifier, headingText, instructionsText)
+{
+    WebInspector.View.call(this);
+
+    this.element.addStyleClass("panel-enabler-view");
+    this.element.addStyleClass(identifier);
+    this.element.addStyleClass("welcome");
+
+    this.contentElement = document.createElement("div");
+    this.contentElement.className = "panel-enabler-view-content";
+    this.element.appendChild(this.contentElement);
+
+    this.alignerElement = document.createElement("div");
+    this.alignerElement.className = "welcome-instructions-aligner";
+    this.contentElement.appendChild(this.alignerElement);
+
+    this.instructionsElement = document.createElement("div");
+    this.instructionsElement.className = "instructions";
+    this.contentElement.appendChild(this.instructionsElement);
+
+    this.headerElement = document.createElement("h1");
+    this.headerElement.textContent = headingText;
+    this.instructionsElement.appendChild(this.headerElement);
+
+    if (instructionsText)
+        this.addMessage(instructionsText);
+}
+
+WebInspector.WelcomeView.prototype = {
+    addMessage: function(message)
+    {
+        var messageElement = document.createElement("div");
+        messageElement.className = "message";
+        if (typeof message == "string")
+            // Message text can contain <br> tags for better text balancing, so we
+            // put it into elements using 'innerHTML', not 'textContent'.
+            messageElement.innerHTML = message;
+        else
+            messageElement.appendChild(message);
+        this.instructionsElement.appendChild(messageElement);
+    }
+}
+
+WebInspector.WelcomeView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/WorkersSidebarPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WorkersSidebarPane.js
new file mode 100644
index 0000000..b254f3c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/WorkersSidebarPane.js
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.WorkersSidebarPane = function()
+{
+    WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers"));
+    
+    this._workers = {};
+
+    this._enableWorkersCheckbox = new WebInspector.Checkbox(
+        WebInspector.UIString("Debug"),
+        "sidebar-pane-subtitle",
+        WebInspector.UIString("Allow debugging workers. Enabling this option will replace native workers with the iframe-based JavaScript implementation"));
+    this.titleElement.insertBefore(this._enableWorkersCheckbox.element, this.titleElement.firstChild);
+
+    this._enableWorkersCheckbox.addEventListener(this._onTriggerInstrument.bind(this));
+    this._enableWorkersCheckbox.checked = false;
+
+    this._listElement = document.createElement("ol");
+    this._listElement.className = "workers-list";
+
+    this.bodyElement.appendChild(this._listElement);
+    this._treeOutline = new TreeOutline(this._listElement);
+}
+
+WebInspector.WorkersSidebarPane.prototype = {
+    addWorker: function(id, url, isShared)
+    {
+        if (id in this._workers) 
+            return;
+        var worker = new WebInspector.Worker(id, url, isShared);
+        this._workers[id] = worker;
+
+        var title = WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url), "worker-item", true, url);
+        var treeElement = new TreeElement(null, worker, false);
+        treeElement.titleHTML = title;
+        this._treeOutline.appendChild(treeElement);
+    },
+
+    removeWorker: function(id)
+    {
+        if (id in this._workers) {
+            this._treeOutline.removeChild(this._treeOutline.findTreeElement(this._workers[id]));
+            delete this._workers[id];
+        }
+    },
+
+    setInstrumentation: function(enabled)
+    {
+        InspectorBackend.removeAllScriptsToEvaluateOnLoad();
+        if (enabled)
+            InspectorBackend.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
+    },
+
+    reset: function()
+    {
+        this.setInstrumentation(this._enableWorkersCheckbox.checked);
+        this._treeOutline.removeChildren();
+        this._workers = {};
+    },
+
+    _onTriggerInstrument: function(event)
+    {
+        this.setInstrumentation(this._enableWorkersCheckbox.checked);
+    }
+};
+
+WebInspector.WorkersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.Worker = function(id, url, shared)
+{
+    this.id = id;
+    this.url = url;
+    this.shared = shared;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/audits.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/audits.css
new file mode 100644
index 0000000..d36efc6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/audits.css
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.audits-sidebar-tree-item .icon {
+    content: url(Images/resourcesTimeGraphIcon.png);
+}
+
+.audit-result-sidebar-tree-item .icon {
+    content: url(Images/resourceDocumentIcon.png);
+}
+
+#audit-views {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 200px;
+    bottom: 0;
+    overflow: auto;
+}
+
+.audit-launcher-view {
+    z-index: 1000;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: white;
+    font-size: 13px;
+    overflow-x: hidden;
+    overflow-y: overlay;
+    display: none;
+}
+
+.audit-launcher-view.visible {
+    display: block;
+}
+
+.audit-launcher-view .audit-launcher-view-content {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding: 0 0 0 16px;
+    white-space: nowrap;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+}
+
+.audit-launcher-view h1 {
+    color: rgb(110, 116, 128);
+    font-size: 16px;
+    line-height: 20px;
+    font-weight: normal;
+    padding-top: 15px;
+}
+
+.audit-launcher-view h1.no-audits {
+    text-align: center;
+    font-style: italic;
+    position: relative;
+    left: -8px;
+}
+
+.audit-launcher-view div.button-container {
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    width: 100%;
+    padding: 16px 0;
+}
+.audit-launcher-view .flexible-space {
+    -webkit-box-flex: 1;
+}
+
+.audit-launcher-view div.audit-categories-container {
+    position: relative;
+    top: 11px;
+    left: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.audit-launcher-view button {
+    color: rgb(6, 6, 6);
+    background-color: transparent;
+    border: 1px solid rgb(165, 165, 165);
+    background-color: rgb(237, 237, 237);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+    -webkit-border-radius: 12px;
+    -webkit-appearance: none;
+}
+
+.audit-launcher-view button {
+    font-size: 13px;
+    padding: 3px 20px;
+    height: 24px;
+    margin: 0 5px 0 0;
+}
+
+.audit-launcher-view button:active {
+    background-color: rgb(215, 215, 215);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+body.inactive .audit-launcher-view button, .audit-launcher-view button:disabled {
+    color: rgb(130, 130, 130);
+    border-color: rgb(212, 212, 212);
+    background-color: rgb(239, 239, 239);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(250, 250, 250)), to(rgb(235, 235, 235)));
+}
+
+.audit-launcher-view label {
+    position: relative;
+    display: block;
+    text-align: left;
+    word-break: break-word;
+    padding: 0 0 5px 0;
+}
+
+.audit-launcher-view label.disabled {
+    color: rgb(130, 130, 130);
+}
+
+.audit-launcher-view input[type="checkbox"] {
+    margin-left: 0;
+}
+
+.audit-launcher-view input[type="radio"] {
+    height: 17px;
+    width: 17px;
+    border: 1px solid rgb(165, 165, 165);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+    -webkit-border-radius: 8px;
+    -webkit-appearance: none;
+    vertical-align: middle;
+    margin: 0 5px 5px 0;
+}
+
+.audit-launcher-view input[type="radio"]:active:not(:disabled) {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+.audit-launcher-view input[type="radio"]:checked:not(:disabled), .audit-launcher-view input[type="radio"]:checked:disabled {
+    background: url(Images/radioDot.png) center no-repeat,
+                -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+}
+
+.audit-launcher-view .resource-progress > img {
+    content: url(Images/spinner.gif);
+    vertical-align: text-top;
+    margin: 0 4px 0 8px;
+}
+
+.audit-result-view {
+    overflow: auto;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    display: none;
+}
+
+.audit-result-view.visible {
+    display: block;
+}
+
+.audit-result-view .severity-severe {
+    content: url(Images/errorRedDot.png);
+}
+
+.audit-result-view .severity-warning {
+    content: url(Images/warningOrangeDot.png);
+}
+
+.audit-result-view .severity-info {
+    content: url(Images/successGreenDot.png);
+}
+
+.audit-result-tree li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 1px;
+    padding-right: 2px;
+}
+
+.audit-result-tree {
+    font-size: 11px;
+    line-height: 14px;
+    -webkit-user-select: text;
+}
+
+.audit-result-tree > ol {
+    position: relative;
+    padding: 2px 6px !important;
+    margin: 0;
+    color: rgb(84, 84, 84);
+    cursor: default;
+    min-width: 100%;
+}
+
+.audit-result-tree, .audit-result-tree ol {
+    list-style-type: none;
+    -webkit-padding-start: 12px;
+    margin: 0;
+}
+
+.audit-result-tree li {
+    padding: 0 0 0 14px;
+    margin-top: 1px;
+    margin-bottom: 1px;
+    word-wrap: break-word;
+    text-indent: -2px;
+}
+
+.audit-result-tree li.parent {
+    text-indent: -12px
+}
+
+.audit-result-tree li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 0;
+    padding-right: 2px;
+}
+
+.audit-result-tree li.parent.expanded::before {
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.audit-result-tree ol.children {
+    display: none;
+}
+
+.audit-result-tree ol.children.expanded {
+    display: block;
+}
+
+.audit-result {
+    font-weight: bold;
+    color: black;
+}
+
+.audit-result img {
+    float: left;
+    margin-left: -40px;
+    margin-top: -1px;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/goToLineDialog.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/goToLineDialog.css
new file mode 100644
index 0000000..725e4c8
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/goToLineDialog.css
@@ -0,0 +1,39 @@
+.go-to-line-dialog {
+    position: absolute;
+    top: 40%;
+    left: 40%;
+    z-index: 1900;
+
+    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#E9E9E9), to(#CFCFCF));
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    padding: 10px;
+    border-radius: 10px;
+    border: 1px solid gray;
+    -webkit-box-shadow: rgb(40,40,40) 0px 0px 50px;
+
+    font-size: 11px;
+    font-family: 'Lucida Grande', sans-serif;
+}
+
+.go-to-line-dialog input {
+    font-size: 11px;
+}
+
+.go-to-line-dialog button {
+    font-size: 11px;
+    color: rgb(6, 6, 6);
+    border: 1px solid rgb(165, 165, 165);
+    background-color: rgb(237, 237, 237);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+    -webkit-border-radius: 12px;
+    -webkit-appearance: none;
+
+    padding: 3px 20px;
+    margin: 0 0 0 10px;
+}
+
+.go-to-line-dialog button:active {
+    background-color: rgb(215, 215, 215);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/heapProfiler.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/heapProfiler.css
new file mode 100644
index 0000000..03a6dd0
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/heapProfiler.css
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.heap-snapshot-sidebar-tree-item .icon {
+    content: url(Images/profileIcon.png);
+}
+
+.heap-snapshot-sidebar-tree-item.small .icon {
+    content: url(Images/profileSmallIcon.png);
+}
+
+.heap-snapshot-view {
+    display: none;
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.heap-snapshot-view.visible {
+    display: block;
+}
+
+.heap-snapshot-view .data-grid {
+    border: none;
+    max-height: 100%;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 93px;
+}
+
+.heap-snapshot-view .data-grid th.count-column {
+    text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.count-column {
+    text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.size-column {
+    text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.size-column {
+    text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.countDelta-column {
+    text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.countDelta-column {
+    text-align: right;
+}
+
+.heap-snapshot-view .data-grid th.sizeDelta-column {
+    text-align: center;
+}
+
+.heap-snapshot-view .data-grid td.sizeDelta-column {
+    text-align: right;
+}
+
+#heap-snapshot-summary-container {
+    position: absolute;
+    padding-top: 20px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 93px;
+    margin-left: -1px;
+    border-left: 1px solid rgb(102, 102, 102);
+    background-color: rgb(101, 111, 130);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
+    background-repeat: repeat-x;
+    background-position: top;
+    text-align: center;
+    text-shadow: black 0 1px 1px;
+    white-space: nowrap;
+    color: white;
+    -webkit-background-size: 1px 6px;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+.heap-snapshot-summary {
+    display: inline-block;
+    width: 50%;
+    min-width: 300px;
+    position: relative;
+}
+
+.heap-snapshot-summary canvas.summary-graph {
+    width: 225px;
+}
+
+.heap-snapshot-summary-label {
+    font-size: 12px;
+    font-weight: bold;
+    position: absolute;
+    top: 1px;
+    width: 50%;
+    left: 25%;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/helpScreen.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/helpScreen.css
new file mode 100644
index 0000000..80a64c6
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/helpScreen.css
@@ -0,0 +1,153 @@
+.help-window-outer {
+    position: absolute;
+    top: 60px;
+    left: 5%;
+    width: 90%;
+    bottom: 40px;
+    z-index: 2000;
+}
+
+body.attached .help-window-outer {
+    top: 32px;
+    left: 0;
+    width: 100%;
+    bottom: 24px;
+}
+
+.help-window-main {
+    max-height: 100%;
+    opacity: 0.85;
+    color: white;
+    background-color: black;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    border: 20px black solid;
+    border-top-width: 0;
+    border-radius: 8px;
+    -webkit-box-shadow: 10px 10px 8px rgba(40, 40, 40, 0.40);
+}
+
+body.attached .help-window-main {
+    border-width: 10px;
+    border-radius: 0;
+    -webkit-box-shadow: 0 0 0;
+}
+
+.help-window-caption {
+    margin: 8px;
+}
+
+body.attached .help-window-caption {
+    display: none;
+}
+
+.help-window-title {
+    border-bottom: solid 1px lightGrey;
+    font-size: 18px;
+    padding-bottom: 6px;
+}
+
+.help-content {
+    overflow-y: auto;
+    overflow-x: hidden;
+    scrollbar-width: 11px;
+    -webkit-box-flex: 1;
+}
+
+.help-content::-webkit-scrollbar {
+    width: 11px;
+}
+
+.help-content::-webkit-scrollbar-corner,
+.help-content::-webkit-resizer {
+    display: none;
+}
+
+.help-content::-webkit-scrollbar-thumb:vertical {
+    background: -webkit-gradient(linear, left top, right top, from(rgb(128, 128, 128)), to(rgb(128, 128, 128)), color-stop(40%, rgb(96, 96, 96)));
+    border-radius: 5px;
+    min-height: 20px;
+}
+
+.help-content::-webkit-scrollbar-thumb:vertical:hover,
+.help-content::-webkit-scrollbar-thumb:vertical:active {
+    background: -webkit-gradient(linear, left top, right top, from(rgb(176, 176, 176)), to(rgb(176, 176, 176)), color-stop(40%, rgb(144, 144, 144)));
+}
+
+.help-content::-webkit-scrollbar-track:vertical {
+    background: -webkit-gradient(linear, left top, right top, from(rgb(10, 10, 10)), to(rgb(32, 32, 32)), color-stop(25%, rgb(32, 32, 32)));
+    border-radius: 5px;
+}
+
+.help-close-button {
+    border: 0;
+    padding: 0;
+    margin: 0px -20px 15px -20px;
+    font-size: 14px;
+    color: rgb(222, 222, 222);
+    background: -webkit-gradient(radial, 30% 30%, 1, 50% 50%, 8, from(rgb(128, 128, 128)), to(rgb(80, 80, 80)));
+    border-radius: 8px;
+    height: 16px;
+    width: 16px;
+}
+
+.help-close-button:hover {
+    color: white;
+}
+
+body.platform-mac .help-close-button {
+    float: left;
+    margin-right: 10px;
+    font-size: 12px;
+}
+
+body:not(.platform-mac) .help-close-button {
+    float: right;
+}
+
+.help-table {
+    width: 100%;
+    font-size: 13px;
+    -webkit-user-select: auto;
+}
+
+.help-table th {
+    padding-top: 6px;
+    text-align: left;
+    color: yellow;
+}
+
+.help-table td {
+    white-space: nowrap;
+    vertical-align: top;
+}
+
+.help-key-cell {
+    text-align: right;
+}
+
+.help-key {
+    color: yellow;
+}
+
+body:not(.platform-mac) .help-key {
+    font-weight: bold;
+    text-shadow: black 1px 1px 7px;
+}
+
+body.platform-mac .help-key {
+    font-family: Lucida Grande, sans-serif;
+    font-size: 13px;
+}
+
+.help-combine-keys {
+    color: white;
+    font-weight: bold;
+    margin: 0 0.3em;
+    font-size: 12px;
+}
+
+.help-key-delimiter {
+    color: white;
+    margin: 0 0.5em;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.css
new file mode 100644
index 0000000..c992806
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.css
@@ -0,0 +1,4329 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2009 Anthony Ricaud <rik@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+html {
+    height: 100%;
+}
+
+body {
+    cursor: default;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    overflow: hidden;
+    font-family: Lucida Grande, sans-serif;
+    font-size: 10px;
+    margin: 0;
+    -webkit-text-size-adjust: none;
+    -webkit-user-select: none;
+}
+
+* {
+    -webkit-box-sizing: border-box;
+}
+
+:focus {
+    outline: none;
+}
+
+input[type="search"]:focus, input[type="text"]:focus {
+    outline: auto 5px -webkit-focus-ring-color;
+}
+
+iframe, a img {
+    border: none;
+}
+
+img {
+    -webkit-user-drag: none;
+}
+
+.hidden {
+    display: none !important;
+}
+
+#toolbar {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 56px;
+    display: -webkit-box;
+    padding: 0 5px;
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
+    border-bottom: 1px solid rgb(80, 80, 80);
+    -webkit-box-orient: horizontal;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+body.inactive #toolbar {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207)));
+    border-bottom: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.detached.platform-mac-leopard #toolbar,
+body.detached.platform-mac-snowleopard #toolbar {
+    background: transparent !important;
+}
+
+body.attached #toolbar {
+    height: 34px;
+    border-top: 1px solid rgb(100, 100, 100);
+    cursor: row-resize;
+    padding-left: 0;
+}
+
+body.attached.port-qt #toolbar {
+    cursor: auto;
+}
+
+body.attached.inactive #toolbar {
+    border-top: 1px solid rgb(64%, 64%, 64%);
+}
+
+.toolbar-item {
+    display: -webkit-box;
+    padding: 4px 6px;
+    margin: 0;
+    background-color: transparent;
+    border-style: none;
+    border-color: transparent;
+    -webkit-box-orient: vertical;
+    -webkit-box-align: center;
+    -webkit-box-pack: end;
+}
+
+.toolbar-item.toggleable.toggled-on {
+    border-width: 0 2px 0 2px;
+    padding: 4px 4px;
+    -webkit-border-image: url(Images/toolbarItemSelected.png) 0 2 0 2;
+}
+
+.toolbar-item.flexable-space {
+    -webkit-box-flex: 1;
+    visibility: hidden;
+}
+
+.toolbar-item input {
+    margin-bottom: 8px;
+}
+
+.toolbar-icon {
+    display: inline-block;
+    width: 32px;
+    height: 32px;
+    -webkit-background-size: 100% auto;
+}
+
+body.attached .toolbar-icon {
+    width: 24px;
+    height: 24px;
+    vertical-align: middle;
+}
+
+.toolbar-item:active .toolbar-icon {
+    background-position: 0 32px;
+}
+
+body.attached .toolbar-item:active .toolbar-icon {
+    background-position: 0 24px;
+}
+
+.toolbar-label {
+    font-size: 11px;
+    font-family: Lucida Grande, sans-serif;
+    text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.toolbar-item.toggleable:active .toolbar-label {
+    text-shadow: none;
+}
+
+body.attached .toolbar-label {
+    display: inline-block;
+    vertical-align: middle;
+    margin-left: 3px;
+}
+
+body.attached #search-toolbar-label {
+    display: none;
+}
+
+#search {
+    width: 205px;
+    font-size: 16px;
+    margin-bottom: 5px;
+}
+
+body.attached #search {
+    font-size: 11px;
+    margin-bottom: 8px;
+}
+
+#search-results-matches {
+    font-size: 11px;
+    text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+    margin-bottom: 22px;
+}
+
+body.attached #search-results-matches {
+    margin-bottom: 6px;
+}
+
+.toolbar-item.elements .toolbar-icon {
+    background-image: url(Images/elementsIcon.png);
+}
+
+.toolbar-item.resources .toolbar-icon {
+    background-image: url(Images/resourcesIcon.png);
+}
+
+.toolbar-item.network .toolbar-icon {
+    background-image: url(Images/networkIcon.png);
+}
+
+.toolbar-item.scripts .toolbar-icon {
+    background-image: url(Images/scriptsIcon.png);
+}
+
+.toolbar-item.timeline .toolbar-icon {
+    background-image: url(Images/timelineIcon.png);
+}
+
+.toolbar-item.profiles .toolbar-icon {
+    background-image: url(Images/profilesIcon.png);
+}
+
+.toolbar-item.audits .toolbar-icon {
+    background-image: url(Images/auditsIcon.png);
+}
+
+.toolbar-item.console .toolbar-icon {
+    background-image: url(Images/consoleIcon.png);
+}
+
+#close-button-left, #close-button-right {
+    width: 14px;
+    height: 14px;
+    background-image: url(Images/closeButtons.png);
+    background-position: 0 0;
+    background-color: transparent;
+    border: 0 none transparent;
+    margin: 5px 0;
+}
+
+#close-button-left:hover, #close-button-right:hover {
+    background-position: 14px 0;
+}
+
+#close-button-left:active, #close-button-right:active {
+    background-position: 28px 0;
+}
+
+body.detached .toolbar-item.close-left, body.detached .toolbar-item.close-right {
+    display: none;
+}
+
+body.attached.port-qt .toolbar-item.close-left, body.attached.port-qt .toolbar-item.close-right {
+    display: none;
+}
+
+body.platform-mac .toolbar-item.close-right {
+    display: none;
+}
+
+body:not(.platform-mac) .toolbar-item.close-left {
+    display: none;
+}
+
+#main {
+    position: absolute;
+    z-index: 1;
+    top: 56px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    overflow: hidden;
+    background-color: white;
+}
+
+body.attached #main {
+    top: 34px;
+}
+
+#main-panels {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 23px;
+    overflow: hidden;
+}
+
+#main-status-bar {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+
+body.drawer-visible #main-status-bar {
+    height: 24px;
+    background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackground.png);
+    background-repeat: no-repeat, repeat-x;
+    background-position: right center, center;
+    cursor: row-resize;
+}
+
+body.drawer-visible #main-status-bar * {
+    cursor: default;
+}
+
+body.drawer-visible #main-panels {
+    bottom: 24px;
+}
+
+.status-bar {
+    background-color: rgb(235, 235, 235);
+    background-image: url(Images/statusbarBackground.png);
+    background-repeat: repeat-x;
+    white-space: nowrap;
+    height: 23px;
+    overflow: hidden;
+    z-index: 12;
+}
+
+.status-bar > div {
+    display: inline-block;
+    vertical-align: top;
+}
+
+.status-bar-item {
+    display: inline-block;
+    height: 24px;
+    padding: 0;
+    margin-left: -1px;
+    margin-right: 0;
+    vertical-align: top;
+    border: 0 transparent none;
+    background-color: transparent;
+}
+
+.status-bar-item:active {
+    position: relative;
+    z-index: 200;
+}
+
+.glyph {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.75);
+    z-index: 1;
+}
+
+.glyph.shadow {
+    top: 1px;
+    background-color: white !important;
+    z-index: 0;
+}
+
+button.status-bar-item {
+    position: relative;
+    width: 32px;
+    background-image: url(Images/statusbarButtons.png);
+    background-position: 0 0;
+}
+
+button.status-bar-item:active {
+    background-position: 32px 0 !important;
+}
+
+button.status-bar-item .glyph.shadow {
+    background-color: rgba(255, 255, 255, 0.33) !important;
+}
+
+button.status-bar-item.toggled-on .glyph {
+    background-color: rgb(66, 129, 235);
+}
+
+button.status-bar-item.toggled-1 .glyph {
+    background-color: rgb(66, 129, 235);
+}
+
+button.status-bar-item.toggled-2 .glyph {
+    background-color: purple;   
+}
+
+button.status-bar-item:disabled {
+    opacity: 0.5;
+    background-position: 0 0 !important;
+}
+
+select.status-bar-item {
+    min-width: 48px;
+    border-width: 0 17px 0 2px;
+    padding: 0 2px 0 6px;
+    font-weight: bold;
+    color: rgb(48, 48, 48);
+    text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+    -webkit-border-image: url(Images/statusbarMenuButton.png) 0 17 0 2;
+    -webkit-border-radius: 0;
+    -webkit-appearance: none;
+}
+
+select.status-bar-item:active {
+    color: black;
+    -webkit-border-image: url(Images/statusbarMenuButtonSelected.png) 0 17 0 2;
+}
+
+#dock-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/undockButtonGlyph.png);
+}
+
+body.detached #dock-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/dockButtonGlyph.png);
+}
+
+body.port-qt #dock-status-bar-item {
+    display: none
+}
+
+#console-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/consoleButtonGlyph.png);
+}
+
+.clear-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png);
+}
+
+#counters {
+    position: absolute;
+    right: 16px;
+    top: 0;
+    cursor: pointer;
+    padding: 6px 2px 6px 0px;
+    font-size: 10px;
+    height: 19px;
+}
+
+#error-warning-count {
+    display: inline;
+}
+
+#error-warning-count:hover {
+    border-bottom: 1px solid rgb(96, 96, 96);
+}
+
+#error-count::before {
+    content: url(Images/errorIcon.png);
+    width: 10px;
+    height: 10px;
+    vertical-align: -1px;
+    margin-right: 2px;
+}
+    
+#error-count + #warning-count {
+    margin-left: 6px;
+}
+
+#warning-count::before {
+    content: url(Images/warningIcon.png);
+    width: 10px;
+    height: 10px;
+    vertical-align: -1px;
+    margin-right: 2px;
+}
+
+#drawer {
+    display: none;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 200px;
+    background-color: white;
+    background-image: url(Images/statusbarBottomBackground.png);
+    background-repeat: repeat-x;
+    background-position: bottom;
+}
+
+body.drawer-visible #drawer {
+    display: block;
+}
+
+#drawer-status-bar {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    background: none;
+}
+
+.monospace {
+    font-size: 10px !important;
+    font-family: monospace;
+}
+
+body.platform-mac .monospace, body.platform-mac .source-code {
+    font-family: Monaco, monospace;
+}
+
+/* Keep .platform-mac to make the rule more specific than the general one above. */
+body.platform-mac.platform-mac-snowleopard .monospace,
+body.platform-mac.platform-mac-snowleopard .source-code {
+    font-size: 11px !important;
+    font-family: Menlo, monospace;
+}
+
+body.platform-windows .monospace, body.platform-windows .source-code {
+    font-size: 12px !important;
+    font-family: Consolas, Lucida Console, monospace;
+}
+
+body.platform-linux .monospace, body.platform-linux .source-code {
+    font-size: 11px !important;
+    font-family: dejavu sans mono, monospace;
+}
+
+#console-messages {
+    position: absolute;
+    z-index: 0;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 23px;
+    padding: 2px 0;
+    overflow-y: overlay;
+    word-wrap: break-word;
+    -webkit-user-select: text;
+    -webkit-text-size-adjust: auto;
+}
+
+#console-prompt {
+    position: relative;
+    padding: 1px 22px 1px 24px;
+    min-height: 16px; 
+    white-space: pre-wrap;
+    -webkit-user-modify: read-write-plaintext-only;
+}
+
+#console-prompt::before {
+    background-image: url(Images/userInputIcon.png);
+}
+
+.console-user-command-result.console-log-level::before {
+    background-image: url(Images/userInputResultIcon.png);
+}
+
+.console-message, .console-user-command {
+    position: relative;
+    border-bottom: 1px solid rgb(240, 240, 240);
+    padding: 1px 22px 1px 24px;
+    min-height: 16px;
+}
+
+.console-adjacent-user-command-result {
+    border-bottom: none;
+}
+
+.console-adjacent-user-command-result + .console-user-command-result.console-log-level::before {
+    background-image: none;
+}
+
+.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title::before {
+    position: absolute;
+    display: block;
+    content: "";
+    left: 7px;
+    top: 0.8em;
+    width: 10px;
+    height: 10px;
+    margin-top: -5px;
+    -webkit-user-select: none;
+}
+
+.console-message .bubble {
+    display: inline-block;
+    height: 14px;
+    background-color: rgb(128, 151, 189);
+    vertical-align: middle;
+    white-space: nowrap;
+    padding: 1px 4px;
+    margin-top: -2px;
+    margin-right: 4px;
+    text-align: left;
+    font-size: 11px;
+    line-height: normal;
+    font-family: Helvetica, Arial, sans-serif;
+    font-weight: bold;
+    text-shadow: none;
+    color: white;
+    -webkit-border-radius: 7px;
+}
+
+.console-message-text {
+    white-space: pre-wrap;
+}
+
+.repeated-message {
+    padding-left: 6px;
+}
+
+.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before, .repeated-message.console-debug-level:before {
+    visibility: hidden;
+}
+
+.console-group .console-group > .console-group-messages {
+    margin-left: 16px;
+}
+
+.console-group-title {
+    font-weight: bold;
+}
+
+.console-group-title::before {
+    background-image: url(Images/disclosureTriangleSmallDown.png);
+    top: 0.6em;
+    width: 11px;
+    height: 12px;
+}
+
+.console-group.collapsed .console-group-title::before {
+    background-image: url(Images/disclosureTriangleSmallRight.png);
+}
+
+.console-group.collapsed > .console-group-messages {
+    display: none;
+}
+
+.console-error-level .console-message-text {
+    color: red;
+}
+
+.console-debug-level .console-message-text {
+    color: blue;
+}
+
+.console-debug-level::before {
+    background-image: url(Images/searchSmallBrightBlue.png);
+}
+
+.console-error-level::before {
+    background-image: url(Images/errorIcon.png);
+}
+
+.console-warning-level::before {
+    background-image: url(Images/warningIcon.png);
+}
+
+.console-user-command .console-message {
+    margin-left: -24px;
+    padding-right: 0;
+    border-bottom: none;
+}
+
+.console-user-command::before {
+    background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.console-user-command > .console-message-text {
+    color: rgb(0, 128, 255);
+}
+
+#console-messages a {
+    color: rgb(33%, 33%, 33%);
+    cursor: pointer;
+}
+
+#console-messages a:hover {
+    color: rgb(15%, 15%, 15%);
+}
+
+.console-message-url {
+    float: right;
+    margin-left: 4px;
+}
+
+.console-group-messages .section {
+    margin: 0 0 0 12px !important;
+}
+
+.console-group-messages .section .header {
+    padding: 0 8px 0 0;
+    background-image: none;
+    border: none;
+    min-height: 0;
+}
+
+.console-group-messages .section .header::before {
+    position: absolute;
+    top: 1px;
+    left: 1px;
+    width: 8px;
+    height: 8px;
+    content: url(Images/treeRightTriangleBlack.png);
+}
+
+.console-group-messages .section.expanded .header::before {
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.console-group-messages .section .header .title {
+    color: black;
+    font-weight: normal;
+}
+
+.console-group-messages .section .properties li .info {
+    padding-top: 0;
+    padding-bottom: 0;
+    color: rgb(60%, 60%, 60%);
+}
+
+.console-group-messages .outline-disclosure {
+    padding-left: 0;
+}
+
+.console-group-messages .outline-disclosure > ol {
+    padding: 0 0 0 12px !important;
+}
+
+.console-group-messages .outline-disclosure, .console-group-messages .outline-disclosure ol {
+    font-size: inherit;
+    line-height: 12px;
+}
+
+.console-group-messages .outline-disclosure.single-node li {
+    padding-left: 2px;
+}
+
+.console-group-messages .outline-disclosure li .selection {
+    margin-left: -6px;
+    margin-right: -6px;
+}
+
+.console-group-messages .add-attribute {
+    display: none;
+}
+
+.console-formatted-object, .console-formatted-node {
+    position: relative;
+    display: inline-block;
+    vertical-align: top;
+}
+
+.console-formatted-object .section, .console-formatted-node .section {
+    position: static;
+}
+
+.console-formatted-object .properties, .console-formatted-node .properties {
+    padding-left: 0 !important;
+}
+
+.console-formatted-number {
+    color: rgb(28, 0, 207);
+}
+
+.console-formatted-string, .console-formatted-regexp {
+    color: rgb(196, 26, 22);
+}
+
+.console-formatted-null, .console-formatted-undefined {
+    color: rgb(128, 128, 128);
+}
+
+.error-message {
+    color: red;
+}
+
+.auto-complete-text, .editing .auto-complete-text {
+    color: rgb(128, 128, 128) !important;
+    -webkit-user-select: none;
+    -webkit-user-modify: read-only;
+}
+
+.panel {
+    display: none;
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.panel.visible {
+    display: block;
+}
+
+.webkit-line-gutter-backdrop {
+    /* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */
+    width: 31px;
+    background-color: rgb(240, 240, 240);
+    border-right: 1px solid rgb(187, 187, 187);
+    position: absolute;
+    z-index: -1;
+    left: 0;
+    top: 0;
+    height: 100%
+}
+
+.resource-view {
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    overflow: auto;
+}
+
+.resource-view.visible {
+    display: block;
+}
+
+.resource-view.font {
+    font-size: 60px;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+    text-align: center;
+    padding: 15px;
+}
+
+.resource-view.image > .image {
+    padding: 20px 20px 10px 20px;
+    text-align: center;
+}
+
+.resource-view.image > .info {
+    padding-bottom: 10px;
+    font-size: 11px;
+    -webkit-user-select: text;
+}
+
+.resource-view.image img.resource-image-view {
+    max-width: 100%;
+    max-height: 1000px;
+    background-image: url(Images/checker.png);
+    -webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);
+    -webkit-user-select: text;
+    -webkit-user-drag: auto;
+}
+
+.resource-url {
+    vertical-align: middle;
+}
+
+.resource-status-image {
+    margin-top: -3px;
+    vertical-align: middle;
+}
+
+.resource-view.image .title {
+    text-align: center;
+    font-size: 13px;
+}
+
+.resource-view.image .infoList {
+    margin: 0;
+}
+
+.resource-view.image .infoList dt {
+    font-weight: bold;
+    display: inline-block;
+    width: 50%;
+    text-align: right;
+    color: rgb(76, 76, 76);
+}
+
+.resource-view.image .infoList dd {
+    display: inline-block;
+    padding-left: 8px;
+    width: 50%;
+    text-align: left;
+    margin: 0;
+}
+
+.resource-view.image .infoList dd::after {
+    white-space: pre;
+    content: "\A";
+}
+
+.resource-timing-row {
+    position: relative;
+    height: 12px;
+}
+
+.resource-timing-bar {
+    position: absolute;
+    background-color: red;
+    border-left: 1px solid red;
+    opacity: 0.4;
+}
+
+.resource-timing-bar-title {
+    position: absolute;
+}
+
+#elements-content {
+    display: block;
+    overflow: auto;
+    padding: 0;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 325px;
+    bottom: 0;
+}
+
+#elements-sidebar {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    width: 325px;
+    border-left: 1px solid rgb(64%, 64%, 64%);
+    cursor: default;
+    overflow: auto;
+}
+
+.crumbs {
+    display: inline-block;
+    font-size: 11px;
+    line-height: 19px;
+    text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+    color: rgb(20, 20, 20);
+    margin-left: -1px;
+    padding-right: 12px;
+}
+
+.crumbs .crumb {
+    height: 24px;
+    border-width: 0 12px 0 2px;
+    -webkit-border-image: url(Images/segment.png) 0 12 0 2;
+    margin-right: -12px;
+    padding-left: 18px;
+    padding-right: 2px;
+    white-space: nowrap;
+    line-height: 23px;
+    float: right;
+}
+
+.crumbs .crumb.collapsed > * {
+    display: none;
+}
+
+.crumbs .crumb.collapsed::before {
+    content: "\2026";
+    font-weight: bold;
+}
+
+.crumbs .crumb.compact .extra {
+    display: none;
+}
+
+.crumbs .crumb.dimmed {
+    color: rgba(0, 0, 0, 0.45);
+}
+
+.crumbs .crumb.start {
+    padding-left: 7px;
+}
+
+.crumbs .crumb.end {
+    border-width: 0 2px 0 2px;
+    padding-right: 6px;
+    -webkit-border-image: url(Images/segmentEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb.selected {
+    -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+    color: black;
+    text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.crumbs .crumb.selected:hover {
+    -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+}
+
+.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover {
+    -webkit-border-image: url(Images/segmentSelectedEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb:hover {
+    -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+    color: black;
+}
+
+.crumbs .crumb.dimmed:hover {
+    -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+    color: rgba(0, 0, 0, 0.75);
+}
+
+.crumbs .crumb.end:hover {
+    -webkit-border-image: url(Images/segmentHoverEnd.png) 0 2 0 2;
+}
+
+.outline-disclosure li.hovered:not(.selected) .selection {
+    display: block;
+    left: 3px;
+    right: 3px;
+    background-color: rgba(56, 121, 217, 0.1);
+    -webkit-border-radius: 5px;
+}
+
+.outline-disclosure li.highlighted .highlight {
+    background-color: rgb(255, 230, 179);
+    -webkit-border-radius: 4px;
+    padding-bottom: 2px;
+    margin-bottom: -2px;
+}
+
+.outline-disclosure li.selected.highlighted .highlight {
+    background-color: transparent;
+    padding-bottom: 0;
+    margin-bottom: 0;
+}
+
+.outline-disclosure li .selection {
+    display: none;
+    position: absolute;
+    left: 0;
+    right: 0;
+    height: 15px;
+    z-index: -1;
+}
+
+.outline-disclosure li.selected .selection {
+    display: block;
+    background-color: rgb(212, 212, 212);
+}
+
+.outline-disclosure ol:focus li.selected .selection {
+    background-color: rgb(56, 121, 217);
+}
+
+.outline-disclosure {
+    font-size: 11px;
+}
+
+.outline-disclosure > ol {
+    position: relative;
+    padding: 2px 6px !important;
+    margin: 0;
+    color: black;
+    cursor: default;
+    min-width: 100%;
+}
+
+.outline-disclosure, .outline-disclosure ol {
+    list-style-type: none;
+    -webkit-padding-start: 12px;
+    margin: 0;
+}
+
+.source-code {
+    font-family: monospace;
+    font-size: 10px !important;
+    white-space: pre-wrap;
+}
+
+.outline-disclosure li {
+    padding: 0 0 0 14px;
+    margin-top: 1px;
+    margin-bottom: 1px;
+    word-wrap: break-word;
+    text-indent: -2px;
+}
+
+.resources .outline-disclosure li {
+    text-indent: -1px;
+}
+
+.outline-disclosure ol:focus li.selected {
+    color: white;
+}
+
+.outline-disclosure ol:focus li.selected * {
+    color: inherit;
+}
+
+.outline-disclosure li.parent {
+    text-indent: -12px
+}
+
+.outline-disclosure li .webkit-html-tag.close {
+    margin-left: -12px;
+}
+
+.outline-disclosure li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 1px;
+    padding-right: 2px;
+}
+
+.outline-disclosure li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+}
+
+.outline-disclosure ol:focus li.parent.selected::before {
+    content: url(Images/treeRightTriangleWhite.png);
+}
+
+.outline-disclosure li.parent.expanded::before {
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.outline-disclosure ol:focus li.parent.expanded.selected::before {
+    content: url(Images/treeDownTriangleWhite.png);
+}
+
+.outline-disclosure ol.children {
+    display: none;
+}
+
+.outline-disclosure ol.children.expanded {
+    display: block;
+}
+
+.add-attribute {
+    margin-left: 1px;
+    margin-right: 1px;
+    white-space: nowrap;
+}
+
+.placard {
+    position: relative;
+    margin-top: 1px;
+    padding: 3px 8px 4px 18px;
+    min-height: 18px;
+    white-space: nowrap;
+}
+
+.placard:nth-of-type(2n) {
+    background-color: rgb(234, 243, 255);
+}
+
+.placard.selected {
+    border-top: 1px solid rgb(145, 160, 192);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+:focus .placard.selected {
+    border-top: 1px solid rgb(68, 128, 200);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .placard.selected {
+    border-top: 1px solid rgb(151, 151, 151);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.placard .title {
+    color: black;
+    font-weight: normal;
+    word-wrap: break-word;
+    white-space: normal;
+}
+
+.placard.selected .title {
+    color: white;
+    font-weight: bold;
+}
+
+.placard .subtitle {
+    float: right;
+    font-size: 10px;
+    margin-left: 5px;
+    max-width: 55%;
+    color: rgba(0, 0, 0, 0.7);
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.placard.selected .subtitle {
+    color: rgba(255, 255, 255, 0.7);
+}
+
+.placard .subtitle a {
+    color: inherit;
+}
+
+.section {
+    position: relative;
+    margin-top: 1px;
+}
+
+.watch-expressions-buttons-container {
+    text-align: center;
+}
+
+.events-pane .section:not(:nth-of-type(1)) {
+    border-top: 1px solid rgb(191, 191, 191);
+}
+
+.event-bar:first-child {
+    margin-top: 1px;
+}
+
+.section .header {
+    color: black;
+    padding: 0 8px 0 18px;
+    min-height: 18px;
+    white-space: nowrap;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+.section .header::before {
+    position: absolute;
+    top: 2px;
+    left: 7px;
+    width: 8px;
+    height: 8px;
+    content: url(Images/treeRightTriangleBlack.png);
+    opacity: 0.8;
+}
+
+.section.expanded .header::before {
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.section .header .title, .event-bar .header .title {
+    font-weight: normal;
+    word-wrap: break-word;
+    white-space: normal;
+    line-height: 18px;
+}
+
+.section .header .title.blank-title {
+    font-style: italic;
+}
+
+.section .header label, .event-bar .header label {
+    display: none;
+}
+
+.section.expanded .header label, .event-bar.expanded .header label {
+    display: inline;
+}
+
+.section .header .subtitle, .event-bar .header .subtitle {
+    float: right;
+    margin-left: 5px;
+    max-width: 55%;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.section .header .subtitle a {
+    color: inherit;
+}
+
+.section .properties, .event-bar .event-properties {
+    display: none;
+}
+
+.section.expanded .properties, .event-bar.expanded .event-properties {
+    display: block;
+    padding-left: 16px;
+}
+
+.section.no-affect .properties li {
+    opacity: 0.5;
+}
+
+.section.no-affect .properties li.editing {
+    opacity: 1.0;
+}
+
+.properties-tree {
+    margin: 0;
+    padding: 0 6px 2px;
+    list-style: none;
+    min-height: 18px;
+}
+
+.properties-tree li {
+    margin-left: 12px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    -webkit-user-select: text;
+    cursor: auto;
+}
+
+.properties-tree li.parent {
+    margin-left: 1px;
+}
+
+.properties-tree li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+    opacity: 0.75;
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 0;
+    padding-right: 3px;
+    -webkit-user-select: none;
+    cursor: default;
+}
+
+.properties-tree li.parent.expanded::before {
+    content: url(Images/treeDownTriangleBlack.png);
+    margin-top: 1px;
+}
+
+.properties-tree li .info {
+    padding-top: 4px;
+    padding-bottom: 3px;
+}
+
+.properties-tree ol {
+    display: none;
+    margin: 0;
+    -webkit-padding-start: 12px;
+    list-style: none;
+}
+
+.properties-tree ol.expanded {
+    display: block;
+}
+
+.event-listener-breakpoints .event-category {
+    font-size: 11px;
+    font-weight: bold;
+    color: rgb(96, 96, 96);
+    padding-top: 2px;
+}
+
+.event-listener-breakpoints.properties-tree .children li {
+    margin-left: 12px;
+    height: 16px;
+}
+
+.event-listener-breakpoints .checkbox-elem {
+    font-size: 10px;
+    float: left;
+    top: -2px;
+    position: relative;
+    left: -1px;
+}
+
+.section .event-bars {
+    display: none;
+}
+
+.section.expanded .event-bars {
+    display: block;
+}
+
+.event-bar {
+    position: relative;
+    margin-left: 10px;
+}
+
+.event-bars .event-bar .header {
+    padding: 0 8px 0 18px;
+    min-height: 16px;
+    opacity: 1.0;
+    white-space: nowrap;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+.event-bars .event-bar .header .title {
+    font-weight: normal;
+    color: black;
+    text-shadow: white 0 1px 0; 
+}
+
+.event-bars .event-bar .header .subtitle {
+    color: rgba(90, 90, 90, 0.75);
+}
+
+.event-bars .event-bar .header::before {
+    position: absolute;
+    top: 2px;
+    left: 7px;
+    width: 8px;
+    height: 8px;
+    opacity: 0.75;
+    content: url(Images/treeRightTriangleBlack.png);
+}
+
+.event-bars .event-bar.expanded .header::before {
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.editing {
+    -webkit-user-select: text;
+    -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px;
+    outline: 1px solid rgb(66%, 66%, 66%) !important;
+    background-color: white;
+    -webkit-user-modify: read-write-plaintext-only;
+    text-overflow: clip !important;
+    padding-left: 2px;
+    margin-left: -2px;
+    padding-right: 2px;
+    margin-right: -2px;
+    margin-bottom: -1px;
+    padding-bottom: 1px;
+    opacity: 1.0 !important;
+}
+
+.editing, .editing * {
+    color: black !important;
+    text-decoration: none !important;
+}
+
+.child-editing {
+    color: black !important;
+    text-decoration: none !important;
+    overflow: visible !important;
+}
+
+.editing br {
+    display: none;
+}
+
+.elements-tree-editor {
+    -webkit-user-select: text;
+    -webkit-user-modify: read-write-plaintext-only;
+}
+
+.section .properties li.editing {
+    margin-left: 10px;
+    text-overflow: clip;
+}
+
+li.editing .swatch, li.editing .enabled-button,  li.editing-sub-part .delete-button {
+    display: none !important;
+}
+
+.watch-expressions > li.editing-sub-part .name {
+    display: block; 
+    width: 100%;
+}
+
+.watch-expressions > li.editing-sub-part .value, .watch-expressions > li.editing-sub-part .separator  {
+    display: none;
+}
+
+.watch-expressions-error-level {
+    color: red;
+}
+
+.section .properties li.editing-sub-part {
+    padding: 3px 6px 8px 18px;
+    margin: -3px -6px -8px -6px;
+    text-overflow: clip;
+}
+
+/* FIXME: need a better icon (comment in bug 27514) */
+.section .properties .delete-button {
+    width: 10px;
+    height: 10px;
+    background-image: url(Images/errorIcon.png);
+    background-position: 0 0;
+    background-color: transparent;
+    background-repeat: no-repeat;
+    border: 0 none transparent;
+}
+
+.section .properties .name, .event-properties .name {
+    color: rgb(136, 19, 145);
+}
+
+.section .properties .value.dimmed {
+    color: rgb(100, 100, 100);
+}
+
+.section .properties .value.error {
+    color: red;
+}
+
+.section .properties .number, .event-properties .number {
+    color: blue;
+}
+
+.section .properties .keyword, .event-properties .keyword {
+    color: rgb(136, 19, 79);
+}
+
+.section .properties .color, .event-properties .color {
+    color: rgb(118, 15, 21);
+}
+
+.swatch {
+    display: inline-block;
+    vertical-align: baseline;
+    margin-left: 1px;
+    margin-right: 2px;
+    margin-bottom: -1px;
+    width: 1em;
+    height: 1em;
+    border: 1px solid rgba(128, 128, 128, 0.6);
+}
+
+.swatch:hover {
+    border: 1px solid rgba(64, 64, 64, 0.8);
+}
+
+.pane:not(.expanded) + .pane, .pane:first-of-type {
+    margin-top: -1px;
+}
+
+.pane > .title {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), color-stop(0.05, rgb(243, 243, 243)), color-stop(0.05, rgb(230, 230, 230)), to(rgb(209, 209, 209)));
+    height: 20px;
+    padding: 0 5px;
+    border-top: 1px solid rgb(189, 189, 189);
+    border-bottom: 1px solid rgb(189, 189, 189);
+    font-weight: bold;
+    font-size: 12px;
+    line-height: 18px;
+    color: rgb(110, 110, 110);
+    text-shadow: white 0 1px 0;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+.pane > .title:active {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(231, 231, 231)), color-stop(0.05, rgb(231, 231, 231)), color-stop(0.05, rgb(207, 207, 207)), to(rgb(186, 186, 186)));
+    border-top: 1px solid rgb(178, 178, 178);
+    border-bottom: 1px solid rgb(178, 178, 178);
+}
+
+.pane > .title::before {
+    content: url(Images/disclosureTriangleSmallRightBlack.png);
+    float: left;
+    width: 11px;
+    height: 12px;
+    margin-right: 2px;
+    margin-top: 1px;
+}
+
+.pane.expanded > .title::before {
+    content: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+.pane > .title > select {
+    float: right;
+    width: 23px;
+    height: 17px;
+    color: transparent;
+    background-color: transparent;
+    border: none;
+    background-image: url(Images/paneSettingsButtons.png);
+    background-repeat: no-repeat;
+    margin: 1px 0 0 0;
+    padding: 0;
+    -webkit-border-radius: 0;
+    -webkit-appearance: none;
+}
+
+.pane > .title > select:hover {
+    background-position: -23px 0px;
+}
+
+.pane > .title > select:active {
+    background-position: -46px 0px;
+}
+
+.pane > .title > select > option, .pane > .title > select > hr {
+    color: black;
+}
+
+.pane > .title > button.add {
+    float: right;
+    width: 23px;
+    height: 17px;
+    color: transparent;
+    background-color: transparent;
+    border: none;
+    background-image: url(Images/paneAddButtons.png);
+    background-repeat: no-repeat;
+    margin: 1px 0 0 0;
+    padding: 0;
+    -webkit-border-radius: 0;
+    -webkit-appearance: none;
+}
+
+.pane > .title > button.add:hover {
+    background-position: -23px 0px;
+}
+
+.pane > .title > button.add:active {
+    background-position: -46px 0px;
+}
+
+.pane > .body {
+    position: relative;
+    display: none;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.pane > .body .info {
+    text-align: center;
+    font-style: italic;
+    font-size: 10px;
+    padding: 6px;
+    color: black;
+}
+
+.pane > .body .placard + .info {
+    border-top: 1px solid rgb(189, 189, 189);
+    background-color: rgb(255, 255, 194);
+}
+
+.pane.expanded > .body, .pane.expanded > .growbar {
+    display: block;
+}
+
+.pane > .body .breakpoint-condition {
+    display: block;
+    margin-top: 4px;
+    margin-bottom: 4px;
+    margin-left: 25px;
+    margin-right: 10px;
+}
+
+.pane.expanded:nth-last-of-type(1) {
+    border-bottom: 1px solid rgb(189, 189, 189);
+}
+
+.pane > .growbar {
+    display: none;
+    background-image: url(Images/paneGrowHandleLine.png), url(Images/paneBottomGrow.png);
+    background-repeat: no-repeat, repeat-x;
+    background-position: center center, bottom;
+    height: 5px;
+}
+
+.sidebar-pane-subtitle {
+    position: absolute;
+    right: 0;
+    font-weight: normal;
+}
+
+body.platform-windows .sidebar-pane-subtitle {
+    padding-top: 1px;
+}
+
+.sidebar-pane-subtitle input, .section .header input[type=checkbox] {
+    font-size: inherit;
+    hight: 1em;
+    width: 1em;
+    margin-left: 0;
+    margin-top: 0;
+    margin-bottom: 0.25em;
+    vertical-align: bottom;
+}
+
+.metrics {
+    padding: 8px;
+    font-size: 10px;
+    text-align: center;
+    white-space: nowrap;
+}
+
+.metrics .label {
+    position: absolute;
+    margin-top: -10px;
+    font-size: 9px;
+    color: grey;
+    background-color: white;
+    margin-left: 3px;
+    padding-left: 2px;
+    padding-right: 2px;
+}
+
+.metrics .position {
+    border: 1px rgb(66%, 66%, 66%) dotted;
+    display: inline-block;
+    text-align: center;
+    padding: 3px;
+    margin: 3px;
+}
+
+.metrics .margin {
+    border: 1px dashed;
+    display: inline-block;
+    text-align: center;
+    vertical-align: middle;
+    padding: 3px;
+    margin: 3px;
+}
+
+.metrics .border {
+    border: 1px black solid;
+    display: inline-block;
+    text-align: center;
+    vertical-align: middle;
+    padding: 3px;
+    margin: 3px;
+}
+
+.metrics .padding {
+    border: 1px grey dashed;
+    display: inline-block;
+    text-align: center;
+    vertical-align: middle;
+    padding: 3px;
+    margin: 3px;
+}
+
+.metrics .content {
+    position: static;
+    border: 1px grey solid;
+    display: inline-block;
+    text-align: center;
+    vertical-align: middle;
+    padding: 3px;
+    margin: 3px;
+    min-width: 80px;
+    text-align: center;
+    overflow: visible;
+}
+
+.metrics .content span {
+    display: inline-block;
+}
+
+.metrics .editing {
+    position: relative;
+    z-index: 100;
+}
+
+.metrics .left {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.metrics .right {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.metrics .top {
+    display: inline-block;
+}
+
+.metrics .bottom {
+    display: inline-block;
+}
+
+.sidebar {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    width: 200px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    background-color: rgb(214, 221, 229);
+    border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.inactive .sidebar {
+    background-color: rgb(232, 232, 232);
+}
+
+.frame-storage-tree-item .icon {
+    content: url(Images/frame.png);
+}
+
+.database-storage-tree-item .icon {
+    content: url(Images/database.png);
+}
+
+.database-table-storage-tree-item .icon {
+    content: url(Images/databaseTable.png);
+}
+
+.domstorage-storage-tree-item.local-storage .icon {
+    content: url(Images/localStorage.png);
+}
+
+.domstorage-storage-tree-item.session-storage .icon {
+    content: url(Images/sessionStorage.png);
+}
+
+.cookie-storage-tree-item .icon {
+    content: url(Images/cookie.png);
+}
+
+.application-cache-storage-tree-item .icon {
+    content: url(Images/applicationCache.png);
+}
+
+/* FIXME: Make separate png for file-system */
+.file-system-storage-tree-item .icon {
+    content: url(Images/applicationCache.png);
+}
+
+#storage-views {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 200px;
+    bottom: 0;
+}
+
+.resources.panel .sidebar {
+    padding-left: 0;
+    z-index: 10;
+}
+
+.resources.panel .sidebar li {
+    height: 17px;
+    white-space: nowrap;
+    text-indent: 0;
+    margin-left: -2px;
+}
+
+.resources.panel .sidebar li.parent {
+    text-indent: 0;
+    margin-left: -12px;
+}
+
+.resources.panel .sidebar li.selected {
+    color: white;
+    text-shadow: rgba(0, 0, 0, 0.33) 0 1px 0;
+    font-weight: bold;
+}
+
+.resources.panel .sidebar li.selected .selection {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+    border-top: 1px solid #979797;
+    height: 17px;
+}
+
+.resources.panel .sidebar :focus li.selected .selection {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+    border-top: 1px solid rgb(68, 128, 200);
+}
+
+body.inactive .resources.panel .sidebar li.selected .selection {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+    border-top: 1px solid rgb(151, 151, 151);
+}
+
+.resources.panel .sidebar .icon {
+    width: 16px;
+    height: 16px;
+    float: left;
+}
+
+.resources.panel .base-storage-tree-element-title {
+    overflow: hidden;
+    position: relative;
+    text-overflow: ellipsis;
+    padding-left: 2px;
+    top: 1px;
+}
+
+li.selected .base-storage-tree-element-subtitle {
+    color: white;
+}
+
+.base-storage-tree-element-subtitle {
+    padding-left: 2px;
+    color: rgb(80, 80, 80);
+    text-shadow: none;
+}
+
+.resources.panel .status {
+    float: right;
+    height: 16px;
+    margin-top: 1px;
+    margin-left: 4px;
+    line-height: 1em;
+}
+
+.resources.panel li .status .bubble {
+    height: 13px;
+    padding-top: 0;
+}
+
+.storage-view {
+    display: none;
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.storage-view.visible {
+    display: block;
+}
+
+.storage-view {
+    overflow: hidden;
+}
+
+.storage-view .data-grid {
+    border: none;
+    height: 100%;
+}
+
+.storage-empty-view, .storage-view .storage-table-error {
+    position: absolute;
+    top: 0;
+    bottom: 25%;
+    left: 0;
+    right: 0;
+    font-size: 24px;
+    color: rgb(75%, 75%, 75%);
+    margin-top: auto;
+    margin-bottom: auto;
+    height: 50px;
+    line-height: 26px;
+    text-align: center;
+    font-weight: bold;
+    padding: 10px;
+    white-space: pre-wrap;
+}
+
+.storage-view .storage-table-error {
+    color: rgb(66%, 33%, 33%);
+}
+
+.data-grid {
+    position: relative;
+    border: 1px solid #aaa;
+}
+
+.data-grid .highlight {
+    background-color: rgb(255, 230, 179);
+}
+
+.data-grid tr.selected .highlight {
+    background-color: transparent;
+}
+
+.data-grid table {
+    table-layout: fixed;
+    border-spacing: 0;
+    border-collapse: collapse;
+    width: 100%;
+    font-size: 10px;
+    font-family: Lucida Grande, sans-serif;
+}
+
+.data-grid .data-container {
+    position: absolute;
+    top: 16px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    padding-right: 14px;
+    overflow-x: hidden;
+    overflow-y: overlay;
+}
+
+.data-grid.inline .data-container {
+    position: static;
+}
+
+.data-grid th {
+    text-align: left;
+    background-image: url(Images/glossyHeader.png);
+    background-repeat: repeat-x;
+    border-right: 1px solid rgb(179, 179, 179);
+    border-bottom: 1px solid rgb(179, 179, 179);
+    height: 15px;
+    font-weight: normal;
+    vertical-align: middle;
+    padding: 0 4px;
+    white-space: nowrap;
+}
+
+.data-grid th.corner {
+    width: 15px;
+    border-right: 0 none transparent;
+}
+
+.data-grid tr.filler {
+    display: table-row !important;
+    height: auto !important;
+}
+
+.data-grid tr.filler td {
+    height: auto !important;
+    padding: 0 !important;
+}
+
+.data-grid table.data {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 16px;
+    bottom: 0;
+    height: 100%;
+    border-top: 0 none transparent;
+    background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255)));
+    -webkit-background-size: 1px 32px;
+}
+
+.data-grid.inline table.data {
+    position: static;
+}
+
+.data-grid table.data tr {
+    display: none;
+}
+
+.data-grid table.data tr.revealed {
+    display: table-row;
+}
+
+.data-grid td {
+    vertical-align: top;
+    height: 12px;
+    line-height: 12px;
+    padding: 2px 4px;
+    white-space: nowrap;
+    border-right: 1px solid #aaa;
+    -webkit-user-select: text;
+}
+
+.data-grid td > div, .data-grid th > div {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.data-grid .centered div {
+    text-align: center;
+}
+
+.data-grid .right div {
+    text-align: right;
+}
+
+.data-grid th.sortable div {
+    position: relative;
+}
+
+.data-grid th.sortable:active {
+    background-image: url(Images/glossyHeaderPressed.png);
+}
+
+.data-grid th.sort-ascending, .data-grid th.sort-descending {
+    border-right: 1px solid rgb(107, 140, 196);
+    border-bottom: 1px solid rgb(107, 140, 196);
+    background-image: url(Images/glossyHeaderSelected.png);
+    background-repeat: repeat-x;
+}
+
+.data-grid th.sortable.sort-ascending:active, .data-grid th.sortable.sort-descending:active {
+    background-image: url(Images/glossyHeaderSelectedPressed.png);
+}
+
+.data-grid th.sort-ascending > div::after {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    height: 12px;
+    margin-bottom: auto;
+    margin-top: auto;
+    width: 8px;
+    content: url(Images/treeUpTriangleBlack.png);
+}
+
+.data-grid th.sort-descending > div::after {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    height: 8px;
+    margin-bottom: auto;
+    margin-top: auto;
+    width: 8px;
+    content: url(Images/treeDownTriangleBlack.png);
+}
+
+.data-grid button {
+    line-height: 19px;
+}
+
+body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-descending {
+    background-image: url(Images/glossyHeader.png);
+    border-right: 1px solid rgb(179, 179, 179);
+    border-bottom: 1px solid rgb(179, 179, 179);
+}
+
+.data-grid tr.parent td.disclosure::before {
+    float: left;
+    content: url(Images/treeRightTriangleBlack.png);
+    width: 8px;
+    height: 8px;
+    margin-right: 2px;
+    -webkit-user-select: none;
+}
+
+.data-grid tr.expanded td.disclosure::before {
+    content: url(Images/treeDownTriangleBlack.png);
+    width: 8px;
+    height: 8px;
+    margin-top: 1px;
+}
+
+.data-grid tr.selected {
+    background-color: rgb(212, 212, 212);
+    color: inherit;
+}
+
+.data-grid:focus tr.selected {
+    background-color: rgb(56, 121, 217);
+    color: white;
+}
+
+.data-grid:focus tr.parent.selected td.disclosure::before {
+    content: url(Images/treeRightTriangleWhite.png);
+}
+
+.data-grid:focus tr.expanded.selected td.disclosure::before {
+    content: url(Images/treeDownTriangleWhite.png);
+}
+
+.data-grid tr:not(.parent) td.disclosure {
+    text-indent: 10px;
+}
+
+.data-grid-resizer {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    width: 5px;
+    z-index: 500;
+    cursor: col-resize;
+}
+
+.storage-view.query {
+    padding: 2px 0;
+    overflow-y: overlay;
+    overflow-x: hidden;
+    -webkit-text-size-adjust: auto;
+}
+
+.database-query-prompt {
+    position: relative;
+    padding: 1px 22px 1px 24px;
+    min-height: 16px; 
+    white-space: pre-wrap;
+    -webkit-user-modify: read-write-plaintext-only;
+    -webkit-user-select: text;
+}
+
+.database-user-query::before, .database-query-prompt::before, .database-query-result::before {
+    position: absolute;
+    display: block;
+    content: "";
+    left: 7px;
+    top: 0.8em;
+    width: 10px;
+    height: 10px;
+    margin-top: -5px;
+    -webkit-user-select: none;
+}
+
+.database-query-prompt::before {
+    background-image: url(Images/userInputIcon.png);
+}
+
+.database-user-query {
+    position: relative;
+    border-bottom: 1px solid rgb(245, 245, 245);
+    padding: 1px 22px 1px 24px;
+    min-height: 16px; 
+}
+
+.database-user-query::before {
+    background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.database-query-text {
+    color: rgb(0, 128, 255);
+    -webkit-user-select: text;
+}
+
+.database-query-result {
+    position: relative;
+    padding: 1px 22px 1px 24px;
+    min-height: 16px;
+    margin-left: -24px;
+    padding-right: 0;
+}
+
+.database-query-result.error {
+    color: red;
+    -webkit-user-select: text;
+}
+
+.database-query-result.error::before {
+    background-image: url(Images/errorIcon.png);
+}
+
+.panel-enabler-view {
+    z-index: 1000;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: white;
+    font-size: 13px;
+    text-align: center;
+    overflow-x: hidden;
+    overflow-y: overlay;
+    display: none;
+}
+
+.panel-enabler-view.visible {
+    display: block;
+}
+
+.panel-enabler-view .panel-enabler-view-content {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    max-height: 390px;
+    margin: auto;
+    white-space: nowrap;
+}
+
+.panel-enabler-view h1 {
+    color: rgb(110, 116, 128);
+    font-size: 16px;
+    line-height: 20px;
+    font-weight: normal;
+    margin-top: 0;
+}
+
+.panel-enabler-disclaimer {
+    font-size: 10px;
+    color: rgb(110, 116, 128);
+    margin-bottom: 12px;
+    margin-left: 20px;
+}
+
+.panel-enabler-disclaimer:empty {
+    display: none;
+}
+
+.panel-enabler-view img, div.welcome-instructions-aligner {
+    height: 100%;
+    min-height: 200px;
+    max-width: 100%;
+    top: 0;
+    bottom: 0;
+    padding: 20px 0 20px 20px;
+    margin: auto;
+    vertical-align: middle;
+}
+
+.panel-enabler-view img.hidden {
+    display: initial !important;
+    width: 0;
+}
+
+.panel-enabler-view form {
+    display: inline-block;
+    vertical-align: middle;
+    width: 330px;
+    margin: 0;
+    padding: 15px;
+    white-space: normal;
+}
+
+.panel-enabler-view label {
+    position: relative;
+    display: block;
+    text-align: left;
+    word-break: break-word;
+    margin: 0 0 5px 20px;
+}
+
+.panel-enabler-view button:not(.status-bar-item), .pane button, button.show-all-nodes {
+    color: rgb(6, 6, 6);
+    background-color: transparent;
+    border: 1px solid rgb(165, 165, 165);
+    background-color: rgb(237, 237, 237);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+    -webkit-border-radius: 12px;
+    -webkit-appearance: none;
+}
+
+.panel-enabler-view button:not(.status-bar-item) {
+    font-size: 13px;
+    margin: 6px 0 0 0;
+    padding: 3px 20px;
+    height: 24px;
+}
+
+button.show-all-nodes {
+    font-size: 13px;
+    margin: 0;
+    padding: 0 20px;
+    height: 20px;
+}
+
+.panel-enabler-view.welcome {
+    z-index: auto;
+}
+
+.panel-enabler-view.welcome div.welcome-instructions-aligner {
+    display: inline-block;
+    width: 0;
+}
+
+.panel-enabler-view.welcome .instructions {
+    display: inline-block;
+    vertical-align: middle;
+    margin: 0;
+    white-space: normal;
+    line-height: 175%;
+}
+
+.panel-enabler-view.welcome .message {
+    margin-bottom: 2ex;
+}
+
+.panel-enabler-view.welcome button.status-bar-item {
+    background-image: none;
+    vertical-align: top;
+}
+
+.pane button {
+    margin: 6px 0 6px 3px;
+    padding: 2px 9px;
+}
+
+.panel-enabler-view button:active:not(.status-bar-item), .pane button:active, button.show-all-nodes:active {
+    background-color: rgb(215, 215, 215);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+body.inactive .panel-enabler-view button:not(.status-bar-item), .panel-enabler-view button:disabled:not(.status-bar-item), body.inactive .pane button, .pane button:disabled, body.inactive button.show-all-nodes {
+    color: rgb(130, 130, 130);
+    border-color: rgb(212, 212, 212);
+    background-color: rgb(239, 239, 239);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(250, 250, 250)), to(rgb(235, 235, 235)));
+}
+
+.panel-enabler-view input {
+    height: 17px;
+    width: 17px;
+    border: 1px solid rgb(165, 165, 165);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+    -webkit-border-radius: 8px;
+    -webkit-appearance: none;
+    vertical-align: middle;
+    margin: 0 5px 5px 0;
+}
+
+.panel-enabler-view input:active {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+.panel-enabler-view input:checked {
+    background: url(Images/radioDot.png) center no-repeat,
+                -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+}
+
+.panel-enabler-view.scripts img {
+    content: url(Images/scriptsSilhouette.png);
+}
+
+.panel-enabler-view.profiles img {
+    content: url(Images/profilesSilhouette.png);
+}
+
+button.enable-toggle-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/enableOutlineButtonGlyph.png);
+}
+
+button.enable-toggle-status-bar-item.toggled-on .glyph {
+    -webkit-mask-image: url(Images/enableSolidButtonGlyph.png);
+}
+
+.scripts-pause-on-exceptions-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png);
+}
+
+#scripts-status-bar {
+    position: absolute;
+    top: -1px;
+    left: 0;
+    right: 0;
+    height: 24px;
+}
+
+#scripts-files {
+    max-width: 250px;
+}
+
+#scripts-files option.extension-script {
+    color: rgb(70, 134, 240);
+}
+
+#scripts-functions {
+    max-width: 150px;
+}
+
+#scripts-status-bar .status-bar-item img {
+    margin-top: 2px;
+}
+
+#scripts-back img {
+    content: url(Images/back.png);
+}
+
+#scripts-forward img {
+    content: url(Images/forward.png);
+}
+
+#scripts-pause img {
+    content: url(Images/debuggerPause.png);
+}
+
+#scripts-pause.paused img {
+    content: url(Images/debuggerContinue.png);
+}
+
+#scripts-step-over img {
+    content: url(Images/debuggerStepOver.png);
+}
+
+#scripts-step-into img {
+    content: url(Images/debuggerStepInto.png);
+}
+
+#scripts-step-out img {
+    content: url(Images/debuggerStepOut.png);
+}
+
+.toggle-breakpoints .glyph {
+    -webkit-mask-image: url(Images/breakpointsActivateButtonGlyph.png);
+    background-color: rgb(96, 96, 96) !important;
+}
+
+.toggle-breakpoints.toggled-on .glyph {
+    -webkit-mask-image: url(Images/breakpointsDeactivateButtonGlyph.png);
+}
+
+#scripts-debugger-status {
+    position: absolute;
+    line-height: 24px;
+    top: 0;
+    right: 8px;
+}
+
+#scripts-sidebar-resizer-widget {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 225px;
+    width: 16px;
+    cursor: col-resize;
+    background-image: url(Images/statusbarResizerHorizontal.png);
+    background-repeat: no-repeat;
+    background-position: center;
+}
+
+#scripts-sidebar-buttons {
+    position: absolute;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    width: 225px;
+    overflow: hidden;
+    border-left: 1px solid rgb(64%, 64%, 64%);
+}
+
+#script-resource-views {
+    display: block;
+    padding: 0;
+    position: absolute;
+    top: 23px;
+    left: 0;
+    right: 225px;
+    bottom: 0;
+}
+
+.script-view {
+    display: none;
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.script-view.visible {
+    display: block;
+}
+
+#scripts-sidebar {
+    position: absolute;
+    top: 23px;
+    right: 0;
+    bottom: 0;
+    width: 225px;
+    border-left: 1px solid rgb(64%, 64%, 64%);
+    cursor: default;
+    overflow: auto;
+}
+
+.resources-larger-resources-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
+}
+
+#resources-filter, #console-filter.console-filter-top {
+    background: -webkit-gradient(linear, left top, left bottom, from(rgb(236, 236, 236)), to(rgb(217, 217, 217)));
+    border-bottom: 1px solid rgb(64%, 64%, 64%);
+    width: 100%;
+}
+
+#console-messages.console-filter-top {
+    margin-top: 23px;
+}
+
+#console-filter {
+    margin-top: 1px;
+}
+
+.tabbed-pane {
+    -webkit-box-orient: vertical;
+    height: 100%;
+}
+
+.tabbed-pane-content {
+    -webkit-box-flex: 1;
+    position: relative;
+}
+
+.tabbed-pane-header {
+    height: 23px;
+    padding: 0 10px;
+    border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.tabbed-pane-header li {
+    display: inline-block;
+    margin-top: 2px;
+    font-size: 11px;
+    font-weight: bold;
+    color: rgb(46, 46, 46);
+    background: transparent;
+    text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+    vertical-align: middle;
+    padding: 3px 7px 2px;
+    height: 21px;
+    border: 1px solid transparent;
+    border-bottom: none;
+}
+
+.tabbed-pane-header li.selected {
+    background-color: white;
+    border: 1px solid rgb(163, 163, 163);
+    border-bottom: none;
+}
+
+.scope-bar {
+    height: 23px;
+    padding: 2px 10px 0;
+    overflow: hidden;
+}
+
+.scope-bar li {
+    display: inline-block;
+    margin: 1px 2px 0 0;
+    padding: 1px 7px 3px;
+    font-size: 11px;
+    line-height: 12px;
+    font-weight: bold;
+    color: rgb(46, 46, 46);
+    background: transparent;
+    text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+    -webkit-border-radius: 8px;
+    vertical-align: middle;
+}
+
+.scope-bar-divider {
+    margin: 1px 9px 0 8px;
+    background-color: rgba(0, 0, 0, 0.4);
+    height: 16px;
+    width: 1px;
+    vertical-align: middle;
+    display: inline-block;
+}
+
+.scope-bar li.selected, .scope-bar li:hover, .scope-bar li:active {
+    color: white;
+    text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
+}
+
+.scope-bar li:hover {
+    background: rgba(0, 0, 0, 0.2);
+}
+
+.scope-bar li.selected {
+    background: rgba(0, 0, 0, 0.3);
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5) inset, 0 -1px 1px rgba(255, 255, 255, 0.25) inset, 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.scope-bar li:active {
+    background: rgba(0, 0, 0, 0.5);
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5) inset, 0 -1px 1px rgba(255, 255, 255, 0.25) inset, 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+#resources-container {
+    position: absolute;
+    top: 23px;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    border-right: 0 none transparent;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+#resources-container.viewing-resource {
+    right: auto;
+    width: 200px;
+    border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+#resources-container.viewing-resource #resources-sidebar {
+    width: 100%;
+    border-right: 0 none transparent;
+}
+
+#resources-sidebar {
+    min-height: 100%;
+    bottom: auto;
+    overflow: visible;
+}
+
+#resources-container-content {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 200px;
+    min-height: 100%;
+}
+
+#resources-container.viewing-resource #resources-container-content {
+    display: none;
+}
+
+#resources-summary {
+    position: absolute;
+    padding-top: 20px;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 93px;
+    margin-left: -1px;
+    border-left: 1px solid rgb(102, 102, 102);
+    background-color: rgb(101, 111, 130);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.5)));
+    background-repeat: repeat-x;
+    background-position: bottom;
+    text-align: center;
+    text-shadow: black 0 1px 1px;
+    white-space: nowrap;
+    color: white;
+    -webkit-background-size: 1px 6px;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+    z-index: 400;
+}
+
+.summary-graph-legend {
+    margin-top: -10px;
+    padding-left: 15px;
+}
+
+.summary-graph-legend-item {
+    display: inline-block;
+    font-weight: bold;
+    margin-right: 15px;
+    vertical-align: top;
+}
+
+.summary-graph-legend-item.total {
+    margin-left: 10px;
+}
+
+.summary-graph-legend-label {
+    display: inline-block;
+    text-align: left;
+}
+
+.summary-graph-legend-header {
+    font-size: 12px;
+}
+
+.summary-graph-legend-value {
+    font-size: 10px;
+}
+
+.summary-graph-legend-swatch {
+    vertical-align: top;
+    margin-top: 1px;
+    margin-right: 3px;
+}
+
+.resources-dividers {
+    position: absolute;
+    left: 0;
+    right: 0;
+    height: 100%;
+    top: 0;
+    z-index: -100;
+}
+
+.resources-event-dividers {
+    position: absolute;
+    left: 0;
+    right: 5px;
+    height: 100%;
+    top: 0;
+    z-index: 300;
+    pointer-events: none;
+}
+
+.timeline .resources-event-dividers {
+    height: 19px;
+}
+
+.resources-dividers-label-bar {
+    position: absolute;
+    top: 0;
+    left: 0px;
+    right: 0;
+    background-color: rgba(255, 255, 255, 0.8);
+    background-clip: padding;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.3);
+    height: 20px;
+    z-index: 200;
+}
+
+.resources-divider {
+    position: absolute;
+    width: 1px;
+    top: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.1);
+}
+
+.resources-event-divider-padding {
+    position: absolute;
+    width: 8px;
+    top: 0;
+    bottom: 0;
+    pointer-events: auto;
+}
+
+.resources-event-divider {
+    position: absolute;
+    width: 2px;
+    top: 0;
+    bottom: 0;
+    z-index: 300;
+}
+
+.resources-red-divider {
+    background-color: rgba(255, 0, 0, 0.5);
+}
+
+.resources-blue-divider {
+    background-color: rgba(0, 0, 255, 0.5);
+}
+
+.resources-orange-divider {
+    background-color: rgba(255, 178, 23, 0.5);
+}
+
+.resources-divider.last {
+    background-color: transparent;
+}
+
+.resources-divider-label {
+    position: absolute;
+    top: 4px;
+    right: 3px;
+    font-size: 9px;
+    color: rgb(50%, 50%, 50%);
+    white-space: nowrap;
+}
+
+.memory-graph-label {
+    position: absolute;
+    top: 5px;
+    left: 5px;
+    font-size: 9px;
+    color: rgb(50%, 50%, 50%);
+    white-space: nowrap;
+}
+
+.resources-graph-label {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto -7px;
+    height: 13px;
+    line-height: 13px;
+    font-size: 9px;
+    color: rgba(0, 0, 0, 0.75);
+    text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
+    z-index: 150;
+    overflow: hidden;
+    text-align: center;
+    font-weight: bold;
+    opacity: 0;
+    -webkit-transition: opacity 250ms ease-in-out;
+}
+
+.resources-graph-side:hover .resources-graph-label {
+    opacity: 1;
+}
+
+.resources-graph-label:empty {
+    display: none;
+}
+
+.resources-graph-label.waiting {
+    margin-right: 5px;
+}
+
+.resources-graph-label.waiting-right {
+    margin-left: 5px;
+}
+
+.resources-graph-label.before {
+    color: rgba(0, 0, 0, 0.7);
+    text-shadow: none;
+    text-align: right;
+    margin-right: 2px;
+}
+
+.resources-graph-label.before::after {
+    padding-left: 2px;
+    height: 6px;
+    content: url(Images/graphLabelCalloutLeft.png);
+}
+
+.resources-graph-label.after {
+    color: rgba(0, 0, 0, 0.7);
+    text-shadow: none;
+    text-align: left;
+    margin-left: 2px;
+}
+
+.resources-graph-label.after::before {
+    padding-right: 2px;
+    height: 6px;
+    content: url(Images/graphLabelCalloutRight.png);
+}
+
+.resources-graph-bar {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto -7px;
+    border-width: 6px 7px;
+    height: 13px;
+    min-width: 14px;
+    opacity: 0.65;
+    -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.resources-category-documents, .resources-category-stylesheets, .resources-category-images,
+.resources-category-scripts, .resources-category-xhr, .resources-category-fonts,
+.resources-category-websockets, .resources-category-other {
+    display: none;
+}
+
+.filter-all .resources-category-documents, .filter-documents .resources-category-documents,
+.filter-all .resources-category-stylesheets, .filter-stylesheets .resources-category-stylesheets,
+.filter-all .resources-category-images, .filter-images .resources-category-images,
+.filter-all .resources-category-scripts, .filter-scripts .resources-category-scripts,
+.filter-all .resources-category-xhr, .filter-xhr .resources-category-xhr,
+.filter-all .resources-category-fonts, .filter-fonts .resources-category-fonts,
+.filter-all .resources-category-websockets, .filter-websockets .resources-category-websockets,
+.filter-all .resources-category-other, .filter-other .resources-category-other,
+.resource-sidebar-tree-item.selected {
+    display: list-item;
+}
+
+.console-warning-level, .console-error-level, .console-log-level {
+    display: none;
+}
+
+.filter-all .console-warning-level, .filter-warnings .console-warning-level,
+.filter-all .console-error-level, .filter-errors .console-error-level,
+.filter-all .console-log-level, .filter-logs .console-log-level {
+    display: block;
+}
+
+.console-user-command-result {
+    display: block;
+}
+
+.resources-graph-bar.waiting, .resources-graph-bar.waiting-right {
+    opacity: 0.35;
+}
+
+.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+.resources-category-documents .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
+}
+
+.resources-category-documents.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
+}
+
+.resources-category-images .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
+}
+
+.resources-category-images.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
+}
+
+.resources-category-fonts .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
+}
+
+.resources-category-fonts.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
+}
+
+.resources-category-scripts .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
+}
+
+.resources-category-scripts.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
+}
+
+.resources-category-xhr .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
+}
+
+.resources-category-xhr.resource-cached .resources-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
+}
+
+/* FIXME: Create bar images for WebSocket. */
+.resources-category-websockets .resources-graph-bar {
+    -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.resources-category-websockets.resource-cached .resources-graph-bar {
+   -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+#resource-views {
+    position: absolute;
+    top: 23px;
+    right: 0;
+    left: 200px;
+    bottom: 0;
+}
+
+.source-view-frame {
+    width: 100%;
+    height: 100%;
+}
+
+.sidebar-resizer-vertical {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    width: 5px;
+    z-index: 500;
+    cursor: col-resize;
+}
+
+.resources .sidebar-resizer-vertical {
+    top: 23px;
+}
+
+.sidebar-tree, .sidebar-tree .children {
+    position: relative;
+    padding: 0;
+    margin: 0;
+    list-style: none;
+    font-size: 11px;
+}
+
+.sidebar-tree-section {
+    position: relative;
+    height: 18px;
+    padding: 4px 10px 6px 10px;
+    white-space: nowrap;
+    margin-top: 1px;
+    color: rgb(92, 110, 129);
+    font-weight: bold;
+    text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+}
+
+.sidebar-tree-item {
+    position: relative;
+    height: 36px;
+    padding: 0 5px 0 5px;
+    white-space: nowrap;
+    margin-top: 1px;
+    line-height: 34px;
+    border-top: 1px solid transparent;
+}
+
+.sidebar-tree .children {
+    display: none;
+}
+
+.sidebar-tree .children.expanded {
+    display: block;
+}
+
+.sidebar-tree-section + .children > .sidebar-tree-item {
+    padding-left: 10px !important;
+}
+
+.sidebar-tree-section + .children.small > .sidebar-tree-item {
+    padding-left: 17px !important;
+}
+
+.sidebar-tree > .children > .sidebar-tree-item {
+    padding-left: 37px;
+}
+
+.sidebar-tree > .children > .children > .sidebar-tree-item {
+    padding-left: 37px;
+}
+
+.sidebar-tree.hide-disclosure-buttons > .children {
+    display: none;
+}
+
+.sidebar-tree > .children.hide-disclosure-buttons > .children {
+    display: none;
+}
+
+.sidebar-tree.some-expandable:not(.hide-disclosure-buttons) > .sidebar-tree-item:not(.parent) .icon {
+    margin-left: 16px;
+}
+
+.sidebar-tree-item .disclosure-button {
+    float: left;
+    width: 16px;
+    height: 100%;
+    border: 0;
+    background-color: transparent;
+    background-image: url(Images/disclosureTriangleSmallRight.png);
+    background-repeat: no-repeat;
+    background-position: center;
+    -webkit-apearance: none;
+}
+
+.sidebar-tree.hide-disclosure-buttons .sidebar-tree-item .disclosure-button {
+    display: none;
+}
+
+body.inactive .sidebar-tree-item .disclosure-button {
+    background-image: url(Images/disclosureTriangleSmallRightBlack.png);
+}
+
+body.inactive .sidebar-tree-item.expanded .disclosure-button {
+    background-image: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+body.inactive .sidebar-tree-item .disclosure-button:active {
+    background-image: url(Images/disclosureTriangleSmallRightDownBlack.png);
+}
+
+.sidebar-tree-item.selected .disclosure-button {
+    background-image: url(Images/disclosureTriangleSmallRightWhite.png) !important;
+}
+
+.sidebar-tree-item.expanded .disclosure-button {
+    background-image: url(Images/disclosureTriangleSmallDown.png);
+}
+
+.sidebar-tree-item.selected.expanded .disclosure-button {
+    background-image: url(Images/disclosureTriangleSmallDownWhite.png) !important;
+}
+
+.sidebar-tree-item.selected .disclosure-button:active {
+    background-image: url(Images/disclosureTriangleSmallRightDownWhite.png) !important;
+}
+
+.sidebar-tree-item .disclosure-button:active {
+    background-image: url(Images/disclosureTriangleSmallRightDown.png);
+}
+
+.sidebar-tree-item .icon {
+    float: left;
+    width: 32px;
+    height: 32px;
+    margin-top: 1px;
+    margin-right: 3px;
+}
+
+li .status {
+    float: right;
+    height: 16px;
+    margin-top: 9px;
+    margin-left: 4px;
+    line-height: 1em;
+}
+
+li .status:empty {
+    display: none;
+}
+
+li .status .bubble {
+    display: inline-block;
+    height: 14px;
+    min-width: 16px;
+    margin-top: 1px;
+    background-color: rgb(128, 151, 189);
+    vertical-align: middle;
+    white-space: nowrap;
+    padding: 1px 4px;
+    text-align: center;
+    font-size: 11px;
+    line-height: normal;
+    font-family: Helvetica, Arial, sans-serif;
+    font-weight: bold;
+    text-shadow: none;
+    color: white;
+    -webkit-border-radius: 7px;
+}
+
+li .status .bubble:empty {
+    display: none;
+}
+
+li.selected .status .bubble {
+    background-color: white !important;
+    color: rgb(132, 154, 190) !important;
+}
+
+:focus li.selected .status .bubble {
+    color: rgb(36, 98, 172) !important;
+}
+
+body.inactive li.selected .status .bubble {
+    color: rgb(159, 159, 159) !important;
+}
+
+.sidebar-tree.small .sidebar-tree-item, .sidebar-tree .children.small .sidebar-tree-item, .sidebar-tree-item.small, .small .resources-graph-side {
+    height: 20px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .icon, .sidebar-tree .children.small .sidebar-tree-item .icon, .sidebar-tree-item.small .icon {
+    width: 16px;
+    height: 16px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .status, .sidebar-tree .children.small .sidebar-tree-item .status, .sidebar-tree-item.small .status {
+    margin-top: 1px;
+}
+
+.sidebar-tree-item.selected {
+    color: white;
+    border-top: 1px solid rgb(145, 160, 192);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+    text-shadow: rgba(0, 0, 0, 0.33) 0 1px 0;
+    font-weight: bold;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+:focus .sidebar-tree-item.selected {
+    border-top: 1px solid rgb(68, 128, 200);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .sidebar-tree-item.selected {
+    border-top: 1px solid rgb(151, 151, 151);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.sidebar-tree-item .titles {
+    position: relative;
+    top: 5px;
+    line-height: 11px;
+    padding-bottom: 1px;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+}
+
+.sidebar-tree-item .titles.no-subtitle {
+    top: 10px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .titles, .sidebar-tree .children.small .sidebar-tree-item .titles, .sidebar-tree-item.small .titles {
+    top: 2px;
+    line-height: normal;
+}
+
+.sidebar-tree:not(.small) .sidebar-tree-item:not(.small) .title::after, .sidebar-tree .children:not(.small) .sidebar-tree-item .title::after {
+    content: "\A";
+    white-space: pre;
+}
+
+.sidebar-tree-item .subtitle {
+    font-size: 9px;
+    color: rgba(0, 0, 0, 0.7);
+}
+
+.sidebar-tree.small .sidebar-tree-item .subtitle, .sidebar-tree .children.small .sidebar-tree-item .subtitle, .sidebar-tree-item.small .subtitle {
+    display: none;
+}
+
+.sidebar-tree-item.selected .subtitle {
+    color: rgba(255, 255, 255, 0.9);
+}
+
+#resources-graphs {
+    position: absolute;
+    left: 0;
+    right: 0;
+    max-height: 100%;
+    top: 112px;
+}
+
+.resources-graph-side {
+    position: relative;
+    height: 36px;
+    padding: 0 5px;
+    white-space: nowrap;
+    margin-top: 1px;
+    border-top: 1px solid transparent;
+    overflow: hidden;
+}
+
+.resources-graph-bar-area {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 8px;
+    left: 9px;
+}
+
+#resources-container:not(.viewing-resource) .resource-sidebar-tree-item:nth-of-type(2n) {
+    background-color: rgba(0, 0, 0, 0.05);
+}
+
+#resources-container:not(.viewing-resource) .resources-graph-side:nth-of-type(2n) {
+    background-color: rgba(0, 0, 0, 0.05);
+}
+
+.resources-time-graph-sidebar-item .icon {
+    content: url(Images/resourcesTimeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+    content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+    content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resource-sidebar-tree-item .icon {
+    content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item .icon {
+    content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-documents .icon {
+    content: url(Images/resourceDocumentIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-documents .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-stylesheets .icon {
+    content: url(Images/resourceCSSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-stylesheets .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-images .icon {
+    position: relative;
+    background-image: url(Images/resourcePlainIcon.png);
+    background-repeat: no-repeat;
+    content: "";
+}
+
+.resources-category-images .image-resource-icon-preview {
+    position: absolute;
+    margin: auto;
+    top: 3px;
+    bottom: 4px;
+    left: 5px;
+    right: 5px;
+    max-width: 18px;
+    max-height: 21px;
+    min-width: 1px;
+    min-height: 1px;
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-images .icon {
+    background-image: url(Images/resourcePlainIconSmall.png);
+    content: "";
+}
+
+.children.small .resources-category-images .image-resource-icon-preview {
+    top: 2px;
+    bottom: 1px;
+    left: 3px;
+    right: 3px;
+    max-width: 8px;
+    max-height: 11px;
+}
+
+.resource-sidebar-tree-item.resources-category-fonts .icon {
+    content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-fonts .icon {
+    content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-scripts .icon {
+    content: url(Images/resourceJSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-scripts .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-xhr .icon {
+    content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-xhr .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.bubble.debug, .console-debug-level .bubble {
+    background-color: rgb(0, 0, 255) !important;
+}
+
+.bubble.warning, .console-warning-level .bubble {
+    background-color: rgb(232, 164, 0) !important;
+}
+
+.bubble.error, .console-error-level .bubble {
+    background-color: rgb(216, 35, 35) !important;
+}
+
+.bubble.search-matches {
+    background-image: url(Images/searchSmallWhite.png);
+    background-repeat: no-repeat;
+    background-position: 3px 2px;
+    padding-left: 13px !important;
+}
+
+li.selected .bubble.search-matches {
+    background-image: url(Images/searchSmallBlue.png);
+}
+
+:focus li.selected .bubble.search-matches {
+    background-image: url(Images/searchSmallBrightBlue.png);
+}
+
+body.inactive li.selected .bubble.search-matches {
+    background-image: url(Images/searchSmallGray.png);
+}
+
+/* Timeline Style */
+
+#timeline-overview-panel {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 80px;
+}
+
+#timeline-overview-panel .timeline-graph-bar {
+    pointer-events: none;
+}
+
+.timeline-sidebar-background {
+    top: 90px;
+    bottom: 0;
+}
+
+.timeline .sidebar {
+    overflow-y: hidden;
+    z-index: 100;
+    min-height: 100%;
+    bottom: auto;
+}
+
+#timeline-overview-separator {
+    position: absolute;
+    top: 80px;
+    left: 0;
+    right: 0;
+    background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(253, 253, 253)), to(rgb(213, 213, 213)));
+    border-top: 1px solid rgb(140, 140, 140);
+    border-bottom: 1px solid rgb(115, 115, 115);
+    height: 10px;
+}
+
+#timeline-overview-sidebar {
+    position: absolute;
+    width: 200px;
+    top: 0px;
+    bottom: 0px;
+    left: 0px;
+    padding-top: 2px;
+    background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(242, 242, 242)), to(rgb(209, 209, 209)));
+    border-right: 1px solid rgb(163, 163, 163);
+}
+
+#timeline-overview-grid {
+    position: absolute;
+    top: 0px;
+    bottom: 0px;
+    left: 200px;
+    right: 0px;
+    background-color: rgb(255, 255, 255);
+}
+
+.timeline-window-selector {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    background-color: rgba(125, 173, 217, 0.5);
+    z-index: 250;
+}
+
+#timeline-overview-window {
+    background-color: white;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 60px;
+    z-index: 150;
+}
+
+.timeline-overview-dividers-background {
+    left: 0%;
+    right: 0%;
+    top: 0px;
+    bottom: 60px;
+    background-color: black;
+    position: absolute;
+}
+
+.timeline-overview-window-rulers {
+    top: 0;
+    bottom: 0;
+    position: absolute;
+    opacity: 0.2;
+    border-right: 1px solid black;
+    border-left: 1px solid black;
+    z-index: 150;
+}
+
+.timeline-window-resizer {
+    position: absolute;
+    top: 0px;
+    bottom: 60px;
+    width: 5px;
+    margin-left: -3px;
+    margin-right: -2px;
+    background-color: rgb(153, 153, 153);
+    z-index: 500;
+    cursor: col-resize;
+    -webkit-border-radius: 2px;
+    -webkit-box-shadow: white 1px 0 0, white -1px 0 0, white 0 1px 0, white 0 -1px 0;
+}
+
+#timeline-overview-grid #resources-graphs {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 80px;
+}
+
+#timeline-container {
+    position: absolute;
+    top: 90px;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    border-right: 0 none transparent;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.timeline-category-statusbar-item {
+    height: 24px;
+    line-height: 24px;
+    padding-left: 6px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    font-weight: bold;
+}
+
+.timeline-category-statusbar-item .timeline-category-checkbox {
+    width: 10px;
+    height: 11px;
+    margin: 0 3px 0 5px;
+    padding: 0;
+    background-image: url(Images/timelineCheckmarks.png);
+    background-repeat: no-repeat;
+    background-position: 0 -66px;
+    vertical-align: -1px;
+    -webkit-appearance: none;
+}
+
+.timeline-category-statusbar-item .timeline-category-checkbox:checked {
+    background-position-x: -10px;
+}
+
+.timeline-category-statusbar-item.timeline-category-loading .timeline-category-checkbox {
+    background-position-y: 0;
+}
+
+.timeline-category-statusbar-item.timeline-category-scripting .timeline-category-checkbox {
+    background-position-y: -33px;
+}
+
+.timeline-category-statusbar-item.timeline-category-rendering .timeline-category-checkbox {
+    background-position-y: -11px;
+}
+
+.timeline-tree-item {
+    height: 18px;
+    line-height: 15px;
+    padding-right: 5px;
+    padding-left: 10px;
+    padding-top: 2px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.timeline-expandable {
+    position: absolute;
+    border-left: 1px solid rgb(163, 163, 163);
+}
+
+.timeline-expandable-left {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    width: 3px;
+    border-top: 1px solid rgb(163, 163, 163);
+    border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.timeline-expandable-collapsed {
+    background-image: url(Images/disclosureTriangleSmallRightBlack.png);
+    background-position-x: 1px;
+    background-position-y: 2px;
+    background-repeat: no-repeat;
+}
+
+.timeline-expandable-expanded {
+    background-image: url(Images/disclosureTriangleSmallDownBlack.png);
+    background-position-x: 1px;
+    background-position-y: 3px;
+    background-repeat: no-repeat;
+}
+
+.timeline-tree-item .type {
+    padding-left: 14px;
+}
+
+.timeline-tree-item .count {
+    font-family: Helvetica, Arial, sans-serif;
+    font-weight: bold;
+}
+
+.timeline-tree-item .timeline-tree-icon {
+    background-image: url(Images/timelineDots.png);
+    margin-top: 2px;
+    width: 12px;
+    height: 12px;
+    position: absolute;
+}
+
+.timeline-tree-item.even {
+    background-color: rgba(0, 0, 0, 0.05);
+}
+
+.timeline-tree-item .data.dimmed {
+    color: rgba(0, 0, 0, 0.7);
+}
+
+#timeline-overview-timelines,
+#timeline-overview-memory {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 20px;
+    z-index: 160;
+}
+
+#timeline-overview-memory > canvas {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 5px;
+}
+
+
+#timeline-graphs {
+    position: absolute;
+    left: 0;
+    right: 0;
+    max-height: 100%;
+    top: 19px;
+}
+
+.timeline-graph-side {
+    position: relative;
+    height: 18px;
+    padding: 0 5px;
+    white-space: nowrap;
+    margin-top: 0px;
+    border-top: 1px solid transparent;
+    overflow: hidden;
+    pointer-events: none;
+}
+
+.timeline-overview-graph-side {
+    height: 20px;
+    z-index: 170;
+    pointer-events: none;
+}
+
+.timeline-overview-graph-side .timeline-graph-bar {
+    height: 13px;
+}
+
+.timeline-graph-bar-area {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    left: 3px;
+    pointer-events: none;
+}
+
+.timeline-graph-bar {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto -2px;
+    border-width: 4px 4px 5px;
+    height: 9px;
+    min-width: 5px;
+    opacity: 0.8;
+    -webkit-border-image: url(Images/timelineBarGray.png) 4 4 5 4;
+    z-index: 180;
+    pointer-events: visibleFill;
+}
+
+.timeline-graph-bar.with-children {
+    opacity: 0.2;
+}
+
+.timeline-graph-bar.cpu {
+    opacity: 0.6;
+}
+
+.timeline-graph-side.even {
+    background-color: rgba(0, 0, 0, 0.05);
+}
+
+.timeline-category-loading .timeline-graph-bar {
+    -webkit-border-image: url(Images/timelineBarBlue.png) 4 4 5 4;
+}
+
+.timeline-category-scripting .timeline-graph-bar {
+    -webkit-border-image: url(Images/timelineBarOrange.png) 4 4 5 4;
+}
+
+.timeline-category-rendering .timeline-graph-bar {
+    -webkit-border-image: url(Images/timelineBarPurple.png) 4 4 5 4;
+}
+
+.timeline-aggregated-category {
+    display: inline-block;
+    height: 11px;
+    margin-right: 2px;
+    margin-left: 6px;
+    position: relative;
+    top: 2px;
+    width: 10px;
+}
+
+.timeline-loading {
+    -webkit-border-image: url(Images/timelineBarBlue.png) 4 4 5 4;
+}
+
+.timeline-scripting {
+    -webkit-border-image: url(Images/timelineBarOrange.png) 4 4 5 4;
+}
+
+.timeline-rendering {
+    -webkit-border-image: url(Images/timelineBarPurple.png) 4 4 5 4;
+}
+
+.popover .timeline-aggregated-category.timeline-loading {
+    margin-left: 0px;
+}
+
+.timeline-category-loading .timeline-tree-icon {
+    background-position-y: 0px;
+}
+
+.timeline-category-scripting .timeline-tree-icon {
+    background-position-y: 48px;
+}
+
+.timeline-category-rendering .timeline-tree-icon {
+    background-position-y: 72px;
+}
+
+.timeline-details {
+    -webkit-user-select: text;
+    vertical-align: top;
+}
+
+.timeline-function-name {
+    text-align: right;
+}
+
+.timeline-stacktrace-title {
+    padding-top: 4px;
+}
+
+.timeline-details-row-title {
+    font-weight: bold;
+    text-align: right;
+    white-space: nowrap;
+}
+
+.timeline-details-row-data {
+    white-space: nowrap;
+}
+
+.timeline-details-title {
+    border-bottom: 1px solid #B8B8B8;
+    font-size: 11px;
+    font-weight: bold;
+    padding-bottom: 5px;
+    padding-top: 0px;
+    white-space: nowrap;
+}
+
+.timeline-filter-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
+}
+
+.timeline-filter-status-bar-item.toggled-on .glyph {
+    background-color: rgb(66, 129, 235) !important;
+}
+
+.timeline-records-counter, .storage-application-cache-status, .storage-application-cache-connectivity {
+    font-size: 11px;
+    text-shadow: white 0 1px 0;
+}
+
+#main-status-bar > .timeline-records-counter {
+    float: right;
+    margin-top: 4px;
+    margin-right: 25px;
+}
+
+#counters > .timeline-records-counter {
+    float: left;
+    margin-top: -2px;
+}
+
+.storage-application-cache-status-icon, .storage-application-cache-connectivity-icon {
+    margin-bottom: -3px;
+    margin-left: 5px;
+    vertical-align: middle;
+}
+
+.status-bar-divider {
+    margin-left: 7px;
+    border-right: 1px solid #CCC;
+}
+
+.storage-application-cache-status, .storage-application-cache-connectivity {
+    position: relative;
+    top: 4px;
+}
+
+/* Profiler Style */
+
+#profile-views {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 200px;
+    bottom: 0;
+}
+
+.status-bar-items {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 200px;
+    overflow: hidden;
+    border-left: 1px solid rgb(184, 184, 184);
+    margin-left: -1px;
+}
+
+.profile-sidebar-tree-item .icon {
+    content: url(Images/profileIcon.png);
+}
+
+.profile-sidebar-tree-item.small .icon {
+    content: url(Images/profileSmallIcon.png);
+}
+
+.profile-group-sidebar-tree-item .icon {
+    content: url(Images/profileGroupIcon.png);
+}
+
+.profile-view {
+    display: none;
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.profile-view.visible {
+    display: block;
+}
+
+.profile-view .data-grid {
+    border: none;
+    height: 100%;
+}
+
+.profile-view .data-grid th.average-column {
+    text-align: center;
+}
+
+.profile-view .data-grid td.average-column {
+    text-align: right;
+}
+
+.profile-view .data-grid th.self-column {
+    text-align: center;
+}
+
+.profile-view .data-grid td.self-column {
+    text-align: right;
+}
+
+.profile-view .data-grid th.total-column {
+    text-align: center;
+}
+
+.profile-view .data-grid td.total-column {
+    text-align: right;
+}
+
+.profile-view .data-grid .calls-column {
+    text-align: center;
+}
+
+.profile-node-file {
+    float: right;
+    color: gray;
+    margin-top: -1px;
+}
+
+.data-grid tr.selected .profile-node-file {
+    color: rgb(33%, 33%, 33%);
+}
+
+.data-grid:focus tr.selected .profile-node-file {
+    color: white;
+}
+
+button.enable-toggle-status-bar-item .glyph {
+}
+
+.record-profile-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/recordButtonGlyph.png);
+}
+
+.record-profile-status-bar-item.toggled-on .glyph {
+    -webkit-mask-image: url(Images/recordToggledButtonGlyph.png);
+    background-color: rgb(216, 0, 0) !important;
+}
+
+/* FIXME: should have its own glyph. */
+.heap-snapshot-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/focusButtonGlyph.png);
+}
+
+.node-search-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/nodeSearchButtonGlyph.png);
+}
+
+.percent-time-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/percentButtonGlyph.png);
+}
+
+.focus-profile-node-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/focusButtonGlyph.png);
+}
+
+.exclude-profile-node-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/excludeButtonGlyph.png);
+}
+
+.reset-profile-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/reloadButtonGlyph.png);
+}
+
+.delete-storage-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/excludeButtonGlyph.png);
+}
+
+.refresh-storage-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/reloadButtonGlyph.png);
+}
+
+ol.breakpoint-list {
+    -webkit-padding-start: 0;
+    list-style: none;
+    margin: 0;
+}
+
+.breakpoint-list li {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    padding: 2px 0;
+    color: black;
+}
+
+.breakpoint-list li:hover {
+    color: rgb(15%, 15%, 15%);
+}
+
+.breakpoint-list .checkbox-elem {
+    font-size: 10px;
+    margin: 0 4px;
+    vertical-align: top;
+    position: relative;
+    z-index: 1;
+}
+
+.breakpoint-list .source-text {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    margin: 2px 0 0px 20px;
+}
+
+.pane .breakpoint-hit {
+    background-color: rgb(255, 255, 194);
+}
+
+li.breakpoint-hit .breakpoint-hit-marker {
+    background-color: rgb(255, 255, 194);
+    height: 18px;
+    left: 0px;
+    margin-top: -16px;
+    position: absolute;
+    right: 0px;
+    z-index: -1;
+}
+
+.webkit-html-js-node, .webkit-html-css-node {
+    white-space: pre;
+}
+
+.source-frame-breakpoint-condition {
+    z-index: 30;
+    padding: 4px;
+    background-color: rgb(203, 226, 255);
+    -webkit-border-radius: 7px;
+    border: 2px solid rgb(169, 172, 203); 
+    width: 90%; 
+}
+
+.source-frame-breakpoint-message {
+    background-color: transparent;
+    font-family: Lucida Grande, sans-serif; 
+    font-weight: normal;
+    font-size: 11px;
+    text-align: left;
+    text-shadow: none;
+    color: rgb(85, 85, 85);
+    cursor: default;
+    margin: 0 0 2px 0; 
+}
+
+#source-frame-breakpoint-condition {
+    margin: 0;
+    border: 1px inset rgb(190, 190, 190) !important;
+    width: 100%;
+    box-shadow: none !important;
+    outline: none !important;
+    -webkit-user-modify: read-write;
+}
+
+.source-frame-popover-title {
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+    font-weight: bold;
+    padding-left: 18px;
+}
+
+.source-frame-popover-tree {
+    border-top: 1px solid rgb(194, 194, 147);
+    overflow: auto;
+    position: absolute;
+    top: 15px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+
+.source-frame-eval-expression {
+    border: 1px solid rgb(163, 41, 34);
+    margin: -1px;
+    background-color: rgb(255, 255, 194);
+}
+
+.styles-sidebar-separator {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), color-stop(0.05, rgb(243, 243, 243)), color-stop(0.05, rgb(230, 230, 230)), to(rgb(209, 209, 209)));
+    padding: 0 5px;
+    border-top: 1px solid rgb(189, 189, 189);
+    border-bottom: 1px solid rgb(189, 189, 189);
+    color: rgb(110, 110, 110);
+    text-shadow: white 0 1px 0;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    font-size: 11px;
+}
+
+.styles-selector {
+    cursor: text;
+}
+
+.workers-list {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+ 
+.workers-list > li {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    margin-left: 1em;
+    font-size: 12px;
+}
+
+a.worker-item {
+    color: rgb(33%, 33%, 33%);
+    cursor: pointer;
+    text-decoration: none;
+}
+
+.styles-section {
+    padding: 2px 2px 4px 4px;
+    min-height: 18px;
+    white-space: nowrap;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+    -webkit-user-select: text;
+}
+
+.styles-section:not(.first-styles-section) {
+    border-top: 1px solid rgb(191, 191, 191);
+}
+
+.styles-section.read-only {
+    background-color: rgb(240, 240, 240);
+}
+
+.styles-section .properties li.not-parsed-ok {
+    margin-left: 0px;
+}
+
+.styles-section .properties li.not-parsed-ok::before {
+    content: url(Images/warningIcon.png);
+    opacity: 0.75;
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 0;
+    padding-right: 5px;
+    vertical-align: sub;
+    -webkit-user-select: none;
+    cursor: default;
+}
+
+.styles-section .header {
+    white-space: nowrap;
+    -webkit-background-origin: padding;
+    -webkit-background-clip: padding;
+}
+
+.styles-section .header .title {
+    word-wrap: break-word;
+    white-space: normal;
+}
+
+.styles-section .header .subtitle {
+    color: rgb(85, 85, 85);
+    float: right;
+    margin-left: 5px;
+    max-width: 65%;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.styles-section .header .subtitle a {
+    color: inherit;
+}
+
+.styles-section a::before {
+    content: attr(data-uncopyable);
+}
+
+.styles-section .properties {
+    display: none;
+    margin: 0;
+    padding: 2px 4px 0 8px;
+    list-style: none;
+}
+
+.styles-section.no-affect .properties li {
+    opacity: 0.5;
+}
+
+.styles-section.no-affect .properties li.editing {
+    opacity: 1.0;
+}
+
+.styles-section.expanded .properties {
+    display: block;
+}
+
+.styles-section .properties li {
+    margin-left: 12px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    cursor: auto;
+}
+
+.styles-section .properties li.parent {
+    margin-left: 1px;
+}
+
+.styles-section .properties ol {
+    display: none;
+    margin: 0;
+    -webkit-padding-start: 12px;
+    list-style: none;
+}
+
+.styles-section .properties ol.expanded {
+    display: block;
+}
+
+.styles-section .properties li.parent::before {
+    content: url(Images/treeRightTriangleBlack.png);
+    opacity: 0.75;
+    float: left;
+    width: 8px;
+    height: 8px;
+    margin-top: 0;
+    padding-right: 3px;
+    -webkit-user-select: none;
+    cursor: default;
+}
+
+.styles-section .properties li.parent.expanded::before {
+    content: url(Images/treeDownTriangleBlack.png);
+    margin-top: 1px;
+}
+
+.styles-section .properties li .info {
+    padding-top: 4px;
+    padding-bottom: 3px;
+}
+
+.styles-section:hover .properties .enabled-button {
+    display: block;
+}
+
+.styles-section .properties li.disabled .enabled-button {
+    display: block;
+}
+
+.styles-section .properties .enabled-button {
+    display: none;
+    float: right;
+    font-size: 10px;
+    margin: 0 0 0 4px;
+    vertical-align: top;
+    position: relative;
+    z-index: 1;
+}
+
+.styles-section .properties .overloaded, .styles-section .properties .inactive, .styles-section .properties .disabled {
+    text-decoration: line-through;
+}
+
+.styles-section.computed-style .properties .disabled {
+    text-decoration: none;
+    opacity: 0.5;
+}
+
+.styles-section .properties .implicit, .styles-section .properties .inherited {
+    opacity: 0.5;
+}
+
+
+.body .styles-section .properties .inherited {
+    display: none;
+}
+
+.body.show-inherited .styles-section .properties .inherited {
+    display: block;
+}
+
+a.worker-item:hover {
+    color: rgb(15%, 15%, 15%);
+}
+
+.resource-content-unavailable {
+    color: rgb(50%, 50%, 50%);
+    font-style: italic;
+    font-size: 14px;
+    text-align: center;
+    padding: 32px;
+}
+
+.node-link {
+    text-decoration: underline;
+    cursor: pointer;
+}
+
+.cursor-pointer {
+    cursor: pointer;
+}
+
+.cursor-auto {
+    cursor: auto;
+}
+
+.please-wait-msg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    border: 4px black solid;
+    border-radius: 4px;
+    background-color: black;
+    opacity: 0.85;
+    color: white;
+    font-size: 12px;
+    font-weight: bold;
+    z-index: 10000;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.html b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.html
new file mode 100644
index 0000000..0435dc3
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.html
@@ -0,0 +1,175 @@
+<!--
+Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1.  Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+2.  Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <link rel="stylesheet" type="text/css" href="audits.css">
+    <link rel="stylesheet" type="text/css" href="goToLineDialog.css">
+    <link rel="stylesheet" type="text/css" href="heapProfiler.css">
+    <link rel="stylesheet" type="text/css" href="inspector.css">
+    <link rel="stylesheet" type="text/css" href="inspectorSyntaxHighlight.css">
+    <link rel="stylesheet" type="text/css" href="networkPanel.css">
+    <link rel="stylesheet" type="text/css" href="helpScreen.css">
+    <link rel="stylesheet" type="text/css" href="popover.css">
+    <link rel="stylesheet" type="text/css" href="textViewer.css">
+    <script type="text/javascript" src="utilities.js"></script>
+    <script type="text/javascript" src="treeoutline.js"></script>
+    <script type="text/javascript" src="inspector.js"></script>
+    <script type="text/javascript" src="InspectorBackendStub.js"></script>
+    <script type="text/javascript" src="InspectorFrontendHostStub.js"></script>
+    <script type="text/javascript" src="ExtensionRegistryStub.js"></script>
+    <script type="text/javascript" src="Object.js"></script>
+    <script type="text/javascript" src="Settings.js"></script>
+    <script type="text/javascript" src="CSSStyleModel.js"></script>
+    <script type="text/javascript" src="Checkbox.js"></script>
+    <script type="text/javascript" src="ContextMenu.js"></script>
+    <script type="text/javascript" src="KeyboardShortcut.js"></script>
+    <script type="text/javascript" src="TextPrompt.js"></script>
+    <script type="text/javascript" src="Popover.js"></script>
+    <script type="text/javascript" src="TabbedPane.js"></script>
+    <script type="text/javascript" src="Placard.js"></script>
+    <script type="text/javascript" src="PleaseWaitMessage.js"></script>
+    <script type="text/javascript" src="View.js"></script>
+    <script type="text/javascript" src="Drawer.js"></script>
+    <script type="text/javascript" src="ConsoleView.js"></script>
+    <script type="text/javascript" src="Panel.js"></script>
+    <script type="text/javascript" src="TimelineGrid.js"></script>    
+    <script type="text/javascript" src="Resource.js"></script>
+    <script type="text/javascript" src="NetworkManager.js"></script>
+    <script type="text/javascript" src="ResourceTreeModel.js"></script>
+    <script type="text/javascript" src="ResourceCategory.js"></script>
+    <script type="text/javascript" src="Database.js"></script>
+    <script type="text/javascript" src="DOMStorage.js"></script>
+    <script type="text/javascript" src="DOMStorageItemsView.js"></script>
+    <script type="text/javascript" src="DataGrid.js"></script>
+    <script type="text/javascript" src="ShowMoreDataGridNode.js"></script>
+    <script type="text/javascript" src="CookiesTable.js"></script>
+    <script type="text/javascript" src="CookieItemsView.js"></script>
+    <script type="text/javascript" src="ApplicationCacheItemsView.js"></script>
+    <script type="text/javascript" src="Script.js"></script>
+    <script type="text/javascript" src="Breakpoint.js"></script>
+    <script type="text/javascript" src="BreakpointManager.js"></script>
+    <script type="text/javascript" src="SidebarPane.js"></script>
+    <script type="text/javascript" src="ElementsTreeOutline.js"></script>
+    <script type="text/javascript" src="SidebarTreeElement.js"></script>
+    <script type="text/javascript" src="Section.js"></script>
+    <script type="text/javascript" src="PropertiesSection.js"></script>
+    <script type="text/javascript" src="RemoteObject.js"></script>
+    <script type="text/javascript" src="ObjectPropertiesSection.js"></script>
+    <script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
+    <script type="text/javascript" src="CallStackSidebarPane.js"></script>
+    <script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+    <script type="text/javascript" src="WatchExpressionsSidebarPane.js"></script>
+    <script type="text/javascript" src="WorkersSidebarPane.js"></script>
+    <script type="text/javascript" src="MetricsSidebarPane.js"></script>
+    <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+    <script type="text/javascript" src="EventListenersSidebarPane.js"></script>
+    <script type="text/javascript" src="Color.js"></script>
+    <script type="text/javascript" src="CSSCompletions.js"></script>
+    <script type="text/javascript" src="CSSKeywordCompletions.js"></script>
+    <script type="text/javascript" src="StylesSidebarPane.js"></script>
+    <script type="text/javascript" src="PanelEnablerView.js"></script>
+    <script type="text/javascript" src="WelcomeView.js"></script>
+    <script type="text/javascript" src="StatusBarButton.js"></script>
+    <script type="text/javascript" src="SummaryBar.js"></script>
+    <script type="text/javascript" src="ElementsPanel.js"></script>
+    <script type="text/javascript" src="NetworkPanel.js"></script>
+    <script type="text/javascript" src="InjectedFakeWorker.js"></script>
+    <script type="text/javascript" src="SourceFrame.js"></script>
+    <script type="text/javascript" src="SourceFrameContent.js"></script>
+    <script type="text/javascript" src="ResourceView.js"></script>
+    <script type="text/javascript" src="ScriptsPanel.js"></script>
+    <script type="text/javascript" src="ResourcesPanel.js"></script>
+    <script type="text/javascript" src="ProfilesPanel.js"></script>
+    <script type="text/javascript" src="ConsolePanel.js"></script>
+    <script type="text/javascript" src="ExtensionAPI.js"></script>
+    <script type="text/javascript" src="ExtensionAuditCategory.js"></script>
+    <script type="text/javascript" src="ExtensionCommon.js"></script>
+    <script type="text/javascript" src="ExtensionServer.js"></script>
+    <script type="text/javascript" src="ExtensionPanel.js"></script>
+    <script type="text/javascript" src="AuditsPanel.js"></script>
+    <script type="text/javascript" src="AuditResultView.js"></script>
+    <script type="text/javascript" src="AuditLauncherView.js"></script>
+    <script type="text/javascript" src="AuditRules.js"></script>
+    <script type="text/javascript" src="AuditCategories.js"></script>
+    <script type="text/javascript" src="AuditFormatters.js"></script>
+    <script type="text/javascript" src="ResourceHeadersView.js"></script>
+    <script type="text/javascript" src="ResourceCookiesView.js"></script>
+    <script type="text/javascript" src="ResourceTimingView.js"></script>
+    <script type="text/javascript" src="NetworkItemView.js"></script>
+    <script type="text/javascript" src="ScriptFormatter.js"></script>
+    <script type="text/javascript" src="DOMSyntaxHighlighter.js"></script>
+    <script type="text/javascript" src="TextEditorModel.js"></script>
+    <script type="text/javascript" src="TextEditorHighlighter.js"></script>
+    <script type="text/javascript" src="TextViewer.js"></script>
+    <script type="text/javascript" src="SourceTokenizer.js"></script>
+    <script type="text/javascript" src="SourceCSSTokenizer.js"></script>
+    <script type="text/javascript" src="SourceHTMLTokenizer.js"></script>
+    <script type="text/javascript" src="SourceJavaScriptTokenizer.js"></script>
+    <script type="text/javascript" src="FontView.js"></script>
+    <script type="text/javascript" src="ImageView.js"></script>
+    <script type="text/javascript" src="DatabaseTableView.js"></script>
+    <script type="text/javascript" src="DatabaseQueryView.js"></script>
+    <script type="text/javascript" src="ProfileDataGridTree.js"></script>
+    <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
+    <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
+    <script type="text/javascript" src="ProfileView.js"></script>
+    <script type="text/javascript" src="HeapSnapshot.js"></script>
+    <script type="text/javascript" src="HeapSnapshotView.js"></script>
+    <script type="text/javascript" src="DetailedHeapshotView.js"></script>
+    <script type="text/javascript" src="DebuggerModel.js"></script>
+    <script type="text/javascript" src="DOMAgent.js"></script>
+    <script type="text/javascript" src="TimelineAgent.js"></script>
+    <script type="text/javascript" src="TimelinePanel.js"></script>
+    <script type="text/javascript" src="TimelineOverviewPane.js"></script>
+    <script type="text/javascript" src="TestController.js"></script>
+    <script type="text/javascript" src="HelpScreen.js"></script>
+    <script type="text/javascript" src="GoToLineDialog.js"></script>
+    <script type="text/javascript" src="ShortcutsHelp.js"></script>
+    <script type="text/javascript" src="HAREntry.js"></script>
+    <script type="text/javascript" src="CookieParser.js"></script>
+</head>
+<body class="detached">
+    <div id="toolbar">
+        <div class="toolbar-item close-left"><button id="close-button-left"></button></div>
+        <div class="toolbar-item flexable-space"></div>
+        <div class="toolbar-item hidden" id="search-results-matches"></div>
+        <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+        <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
+    </div>
+    <div id="main">
+        <div id="main-panels" spellcheck="false"></div>
+        <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><div id="counters"><div id="error-warning-count" class="hidden"></div></div></div></div>
+    </div>
+    <div id="drawer">
+        <div id="console-view"><div id="console-messages" class="monospace"><div id="console-prompt" spellcheck="false"><br></div></div></div>
+        <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item clear-status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><div id="console-filter" class="scope-bar status-bar-item"></div></div></div>
+    </div>
+</body>
+</html>
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.js
new file mode 100644
index 0000000..0959289
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspector.js
@@ -0,0 +1,1927 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Keep this ; so that concatenated version of the script worked.
+;(function preloadImages()
+{
+    (new Image()).src = "Images/clearConsoleButtonGlyph.png";
+    (new Image()).src = "Images/consoleButtonGlyph.png";
+    (new Image()).src = "Images/dockButtonGlyph.png";
+    (new Image()).src = "Images/enableOutlineButtonGlyph.png";
+    (new Image()).src = "Images/enableSolidButtonGlyph.png";
+    (new Image()).src = "Images/excludeButtonGlyph.png";
+    (new Image()).src = "Images/focusButtonGlyph.png";
+    (new Image()).src = "Images/largerResourcesButtonGlyph.png";
+    (new Image()).src = "Images/nodeSearchButtonGlyph.png";
+    (new Image()).src = "Images/pauseOnExceptionButtonGlyph.png";
+    (new Image()).src = "Images/percentButtonGlyph.png";
+    (new Image()).src = "Images/recordButtonGlyph.png";
+    (new Image()).src = "Images/recordToggledButtonGlyph.png";
+    (new Image()).src = "Images/reloadButtonGlyph.png";
+    (new Image()).src = "Images/undockButtonGlyph.png";
+})();
+
+var WebInspector = {
+    resources: {},
+    missingLocalizedStrings: {},
+    pendingDispatches: 0,
+
+    get platform()
+    {
+        if (!("_platform" in this))
+            this._platform = InspectorFrontendHost.platform();
+
+        return this._platform;
+    },
+
+    get platformFlavor()
+    {
+        if (!("_platformFlavor" in this))
+            this._platformFlavor = this._detectPlatformFlavor();
+
+        return this._platformFlavor;
+    },
+
+    _detectPlatformFlavor: function()
+    {
+        const userAgent = navigator.userAgent;
+
+        if (this.platform === "windows") {
+            var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/);
+            if (match && match[1] >= 6)
+                return WebInspector.PlatformFlavor.WindowsVista;
+            return null;
+        } else if (this.platform === "mac") {
+            var match = userAgent.match(/Mac OS X\s*(?:(\d+)_(\d+))?/);
+            if (!match || match[1] != 10)
+                return WebInspector.PlatformFlavor.MacSnowLeopard;
+            switch (Number(match[2])) {
+                case 4:
+                    return WebInspector.PlatformFlavor.MacTiger;
+                case 5:
+                    return WebInspector.PlatformFlavor.MacLeopard;
+                case 6:
+                default:
+                    return WebInspector.PlatformFlavor.MacSnowLeopard;
+            }
+        }
+
+        return null;
+    },
+
+    get port()
+    {
+        if (!("_port" in this))
+            this._port = InspectorFrontendHost.port();
+
+        return this._port;
+    },
+
+    get previousFocusElement()
+    {
+        return this._previousFocusElement;
+    },
+
+    get currentFocusElement()
+    {
+        return this._currentFocusElement;
+    },
+
+    set currentFocusElement(x)
+    {
+        if (this._currentFocusElement !== x)
+            this._previousFocusElement = this._currentFocusElement;
+        this._currentFocusElement = x;
+
+        if (this._currentFocusElement) {
+            this._currentFocusElement.focus();
+
+            // Make a caret selection inside the new element if there isn't a range selection and
+            // there isn't already a caret selection inside.
+            var selection = window.getSelection();
+            if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
+                var selectionRange = this._currentFocusElement.ownerDocument.createRange();
+                selectionRange.setStart(this._currentFocusElement, 0);
+                selectionRange.setEnd(this._currentFocusElement, 0);
+
+                selection.removeAllRanges();
+                selection.addRange(selectionRange);
+            }
+        } else if (this._previousFocusElement)
+            this._previousFocusElement.blur();
+    },
+
+    get currentPanel()
+    {
+        return this._currentPanel;
+    },
+
+    set currentPanel(x)
+    {
+        if (this._currentPanel === x)
+            return;
+
+        if (this._currentPanel)
+            this._currentPanel.hide();
+
+        this._currentPanel = x;
+
+        this.updateSearchLabel();
+
+        if (x) {
+            x.show();
+
+            if (this.currentQuery) {
+                if (x.performSearch) {
+                    function performPanelSearch()
+                    {
+                        this.updateSearchMatchesCount();
+
+                        x.currentQuery = this.currentQuery;
+                        x.performSearch(this.currentQuery);
+                    }
+
+                    // Perform the search on a timeout so the panel switches fast.
+                    setTimeout(performPanelSearch.bind(this), 0);
+                } else {
+                    // Update to show Not found for panels that can't be searched.
+                    this.updateSearchMatchesCount();
+                }
+            }
+        }
+
+        for (var panelName in WebInspector.panels) {
+            if (WebInspector.panels[panelName] === x) {
+                WebInspector.settings.lastActivePanel = panelName;
+                this._panelHistory.setPanel(panelName);
+            }
+        }
+    },
+
+    createDOMBreakpointsSidebarPane: function()
+    {
+        var pane = new WebInspector.NativeBreakpointsSidebarPane(WebInspector.UIString("DOM Breakpoints"));
+        function breakpointAdded(event)
+        {
+            pane.addBreakpointItem(new WebInspector.BreakpointItem(event.data));
+        }
+        WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.DOMBreakpointAdded, breakpointAdded);
+        return pane;
+    },
+
+    createXHRBreakpointsSidebarPane: function()
+    {
+        var pane = new WebInspector.XHRBreakpointsSidebarPane();
+        function breakpointAdded(event)
+        {
+            pane.addBreakpointItem(new WebInspector.BreakpointItem(event.data));
+        }
+        WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.XHRBreakpointAdded, breakpointAdded);
+        return pane;
+    },
+
+    _createPanels: function()
+    {
+        var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(',');
+        if (hiddenPanels.indexOf("elements") === -1)
+            this.panels.elements = new WebInspector.ElementsPanel();
+        if (hiddenPanels.indexOf("resources") === -1)
+            this.panels.resources = new WebInspector.ResourcesPanel();
+        if (hiddenPanels.indexOf("network") === -1)
+            this.panels.network = new WebInspector.NetworkPanel();
+        if (hiddenPanels.indexOf("scripts") === -1)
+            this.panels.scripts = new WebInspector.ScriptsPanel();
+        if (hiddenPanels.indexOf("timeline") === -1)
+            this.panels.timeline = new WebInspector.TimelinePanel();
+        if (hiddenPanels.indexOf("profiles") === -1) {
+            this.panels.profiles = new WebInspector.ProfilesPanel();
+            this.panels.profiles.registerProfileType(new WebInspector.CPUProfileType());
+            if (Preferences.heapProfilerPresent) {
+                if (!Preferences.detailedHeapProfiles)
+                    this.panels.profiles.registerProfileType(new WebInspector.HeapSnapshotProfileType());
+                else
+                    this.panels.profiles.registerProfileType(new WebInspector.DetailedHeapshotProfileType());
+            }
+        }
+        if (hiddenPanels.indexOf("audits") === -1)
+            this.panels.audits = new WebInspector.AuditsPanel();
+        if (hiddenPanels.indexOf("console") === -1)
+            this.panels.console = new WebInspector.ConsolePanel();
+    },
+
+    get attached()
+    {
+        return this._attached;
+    },
+
+    set attached(x)
+    {
+        if (this._attached === x)
+            return;
+
+        this._attached = x;
+
+        this.updateSearchLabel();
+
+        var dockToggleButton = document.getElementById("dock-status-bar-item");
+        var body = document.body;
+
+        if (x) {
+            body.removeStyleClass("detached");
+            body.addStyleClass("attached");
+            dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+        } else {
+            body.removeStyleClass("attached");
+            body.addStyleClass("detached");
+            dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+        }
+        if (this.drawer)
+            this.drawer.resize();
+    },
+
+    get errors()
+    {
+        return this._errors || 0;
+    },
+
+    set errors(x)
+    {
+        x = Math.max(x, 0);
+
+        if (this._errors === x)
+            return;
+        this._errors = x;
+        this._updateErrorAndWarningCounts();
+    },
+
+    get warnings()
+    {
+        return this._warnings || 0;
+    },
+
+    set warnings(x)
+    {
+        x = Math.max(x, 0);
+
+        if (this._warnings === x)
+            return;
+        this._warnings = x;
+        this._updateErrorAndWarningCounts();
+    },
+
+    _updateErrorAndWarningCounts: function()
+    {
+        var errorWarningElement = document.getElementById("error-warning-count");
+        if (!errorWarningElement)
+            return;
+
+        if (!this.errors && !this.warnings) {
+            errorWarningElement.addStyleClass("hidden");
+            return;
+        }
+
+        errorWarningElement.removeStyleClass("hidden");
+
+        errorWarningElement.removeChildren();
+
+        if (this.errors) {
+            var errorElement = document.createElement("span");
+            errorElement.id = "error-count";
+            errorElement.textContent = this.errors;
+            errorWarningElement.appendChild(errorElement);
+        }
+
+        if (this.warnings) {
+            var warningsElement = document.createElement("span");
+            warningsElement.id = "warning-count";
+            warningsElement.textContent = this.warnings;
+            errorWarningElement.appendChild(warningsElement);
+        }
+
+        if (this.errors) {
+            if (this.warnings) {
+                if (this.errors == 1) {
+                    if (this.warnings == 1)
+                        errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings);
+                    else
+                        errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings);
+                } else if (this.warnings == 1)
+                    errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings);
+                else
+                    errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings);
+            } else if (this.errors == 1)
+                errorWarningElement.title = WebInspector.UIString("%d error", this.errors);
+            else
+                errorWarningElement.title = WebInspector.UIString("%d errors", this.errors);
+        } else if (this.warnings == 1)
+            errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings);
+        else if (this.warnings)
+            errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings);
+        else
+            errorWarningElement.title = null;
+    },
+
+    highlightDOMNode: function(nodeId)
+    {
+        if ("_hideDOMNodeHighlightTimeout" in this) {
+            clearTimeout(this._hideDOMNodeHighlightTimeout);
+            delete this._hideDOMNodeHighlightTimeout;
+        }
+
+        if (this._highlightedDOMNodeId === nodeId)
+            return;
+
+        this._highlightedDOMNodeId = nodeId;
+        if (nodeId)
+            InspectorBackend.highlightDOMNode(nodeId);
+        else
+            InspectorBackend.hideDOMNodeHighlight();
+    },
+
+    highlightDOMNodeForTwoSeconds: function(nodeId)
+    {
+        this.highlightDOMNode(nodeId);
+        this._hideDOMNodeHighlightTimeout = setTimeout(this.highlightDOMNode.bind(this, 0), 2000);
+    },
+
+    wireElementWithDOMNode: function(element, nodeId)
+    {
+        element.addEventListener("click", this._updateFocusedNode.bind(this, nodeId), false);
+        element.addEventListener("mouseover", this.highlightDOMNode.bind(this, nodeId), false);
+        element.addEventListener("mouseout", this.highlightDOMNode.bind(this, 0), false);
+    },
+
+    _updateFocusedNode: function(nodeId)
+    {
+        this.currentPanel = this.panels.elements;
+        this.panels.elements.updateFocusedNode(nodeId);
+    },
+
+    get networkResources()
+    {
+        return this.panels.network.resources;
+    },
+
+    networkResourceById: function(id)
+    {
+        return this.panels.network.resourceById(id);
+    },
+
+    forAllResources: function(callback)
+    {
+        WebInspector.resourceTreeModel.forAllResources(callback);
+    },
+
+    resourceForURL: function(url)
+    {
+        return this.resourceTreeModel.resourceForURL(url);
+    },
+
+    openLinkExternallyLabel: function()
+    {
+        return WebInspector.UIString("Open Link in New Window");
+    }
+}
+
+WebInspector.PlatformFlavor = {
+    WindowsVista: "windows-vista",
+    MacTiger: "mac-tiger",
+    MacLeopard: "mac-leopard",
+    MacSnowLeopard: "mac-snowleopard"
+};
+
+(function parseQueryParameters()
+{
+    WebInspector.queryParamsObject = {};
+    var queryParams = window.location.search;
+    if (!queryParams)
+        return;
+    var params = queryParams.substring(1).split("&");
+    for (var i = 0; i < params.length; ++i) {
+        var pair = params[i].split("=");
+        WebInspector.queryParamsObject[pair[0]] = pair[1];
+    }
+})();
+
+WebInspector.loaded = function()
+{
+    if ("page" in WebInspector.queryParamsObject) {
+        var page = WebInspector.queryParamsObject.page;
+        var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host;
+        WebInspector.socket = new WebSocket("ws://" + host + "/devtools/page/" + page);
+        WebInspector.socket.onmessage = function(message) { InspectorBackend.dispatch(message.data); }
+        WebInspector.socket.onerror = function(error) { console.error(error); }
+        WebInspector.socket.onopen = function() {
+            InspectorFrontendHost.sendMessageToBackend = WebInspector.socket.send.bind(WebInspector.socket);
+            InspectorFrontendHost.loaded = WebInspector.socket.send.bind(WebInspector.socket, "loaded");
+            WebInspector.doLoadedDone();
+        }
+        return;
+    }
+    WebInspector.doLoadedDone();
+}
+
+WebInspector.doLoadedDone = function()
+{
+    InspectorFrontendHost.loaded();
+
+    var platform = WebInspector.platform;
+    document.body.addStyleClass("platform-" + platform);
+    var flavor = WebInspector.platformFlavor;
+    if (flavor)
+        document.body.addStyleClass("platform-" + flavor);
+    var port = WebInspector.port;
+    document.body.addStyleClass("port-" + port);
+
+    WebInspector.settings = new WebInspector.Settings();
+
+    this._registerShortcuts();
+
+    // set order of some sections explicitly
+    WebInspector.shortcutsHelp.section(WebInspector.UIString("Console"));
+    WebInspector.shortcutsHelp.section(WebInspector.UIString("Elements Panel"));
+
+    this.drawer = new WebInspector.Drawer();
+    this.console = new WebInspector.ConsoleView(this.drawer);
+    this.drawer.visibleView = this.console;
+    this.resourceTreeModel = new WebInspector.ResourceTreeModel();
+    this.networkManager = new WebInspector.NetworkManager(this.resourceTreeModel);
+    this.domAgent = new WebInspector.DOMAgent();
+
+    InspectorBackend.registerDomainDispatcher("Inspector", this);
+
+    this.resourceCategories = {
+        documents: new WebInspector.ResourceCategory("documents", WebInspector.UIString("Documents"), "rgb(47,102,236)"),
+        stylesheets: new WebInspector.ResourceCategory("stylesheets", WebInspector.UIString("Stylesheets"), "rgb(157,231,119)"),
+        images: new WebInspector.ResourceCategory("images", WebInspector.UIString("Images"), "rgb(164,60,255)"),
+        scripts: new WebInspector.ResourceCategory("scripts", WebInspector.UIString("Scripts"), "rgb(255,121,0)"),
+        xhr: new WebInspector.ResourceCategory("xhr", WebInspector.UIString("XHR"), "rgb(231,231,10)"),
+        fonts: new WebInspector.ResourceCategory("fonts", WebInspector.UIString("Fonts"), "rgb(255,82,62)"),
+        websockets: new WebInspector.ResourceCategory("websockets", WebInspector.UIString("WebSockets"), "rgb(186,186,186)"), // FIXME: Decide the color.
+        other: new WebInspector.ResourceCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)")
+    };
+
+    this.cssModel = new WebInspector.CSSStyleModel();
+    this.debuggerModel = new WebInspector.DebuggerModel();
+
+    this.breakpointManager = new WebInspector.BreakpointManager();
+
+    this.panels = {};
+    this._createPanels();
+    this._panelHistory = new WebInspector.PanelHistory();
+
+    var toolbarElement = document.getElementById("toolbar");
+    var previousToolbarItem = toolbarElement.children[0];
+
+    this.panelOrder = [];
+    for (var panelName in this.panels)
+        previousToolbarItem = WebInspector.addPanelToolbarIcon(toolbarElement, this.panels[panelName], previousToolbarItem);
+
+    this.Tips = {
+        ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
+    };
+
+    this.Warnings = {
+        IncorrectMIMEType: {id: 0, message: WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s.")}
+    };
+
+    this.addMainEventListeners(document);
+
+    window.addEventListener("resize", this.windowResize.bind(this), true);
+
+    document.addEventListener("focus", this.focusChanged.bind(this), true);
+    document.addEventListener("keydown", this.documentKeyDown.bind(this), false);
+    document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
+    document.addEventListener("copy", this.documentCopy.bind(this), true);
+    document.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true);
+
+    var dockToggleButton = document.getElementById("dock-status-bar-item");
+    dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false);
+
+    if (this.attached)
+        dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+    else
+        dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+
+    var errorWarningCount = document.getElementById("error-warning-count");
+    errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
+    this._updateErrorAndWarningCounts();
+
+    var searchField = document.getElementById("search");
+    searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
+    searchField.addEventListener("mousedown", this._searchFieldManualFocus.bind(this), false); // when the search field is manually selected
+    searchField.addEventListener("keydown", this._searchKeyDown.bind(this), true);
+
+    toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true);
+    document.getElementById("close-button-left").addEventListener("click", this.close, true);
+    document.getElementById("close-button-right").addEventListener("click", this.close, true);
+
+    this.extensionServer.initExtensions();
+
+    function onPopulateScriptObjects()
+    {
+        if (!WebInspector.currentPanel)
+            WebInspector.showPanel(WebInspector.settings.lastActivePanel);
+    }
+    InspectorBackend.populateScriptObjects(onPopulateScriptObjects);
+
+    if (Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled)
+        this.debuggerModel.enableDebugger();
+    if (Preferences.profilerAlwaysEnabled || WebInspector.settings.profilerEnabled)
+        InspectorBackend.enableProfiler();
+    if (WebInspector.settings.monitoringXHREnabled)
+        InspectorBackend.setMonitoringXHREnabled(true);
+
+    InspectorBackend.setConsoleMessagesEnabled(true);
+
+    function propertyNamesCallback(names)
+    {
+        WebInspector.cssNameCompletions = new WebInspector.CSSCompletions(names);
+    }
+    // As a DOMAgent method, this needs to happen after the frontend has loaded and the agent is available.
+    InspectorBackend.getSupportedCSSProperties(propertyNamesCallback);
+}
+
+WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
+{
+    var panelToolbarItem = panel.toolbarItem;
+    this.panelOrder.push(panel);
+    panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
+    if (previousToolbarItem)
+        toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
+    else
+        toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
+    return panelToolbarItem;
+}
+
+var windowLoaded = function()
+{
+    var localizedStringsURL = InspectorFrontendHost.localizedStringsURL();
+    if (localizedStringsURL) {
+        var localizedStringsScriptElement = document.createElement("script");
+        localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
+        localizedStringsScriptElement.type = "text/javascript";
+        localizedStringsScriptElement.src = localizedStringsURL;
+        document.head.appendChild(localizedStringsScriptElement);
+    } else
+        WebInspector.loaded();
+
+    window.removeEventListener("DOMContentLoaded", windowLoaded, false);
+    delete windowLoaded;
+};
+
+window.addEventListener("DOMContentLoaded", windowLoaded, false);
+
+WebInspector.dispatch = function(message) {
+    // We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
+    // This is important to LayoutTests.
+    function delayDispatch()
+    {
+        InspectorBackend.dispatch(message);
+        WebInspector.pendingDispatches--;
+    }
+    WebInspector.pendingDispatches++;
+    setTimeout(delayDispatch, 0);
+}
+
+WebInspector.dispatchMessageFromBackend = function(messageObject)
+{
+    WebInspector.dispatch(messageObject);
+}
+
+WebInspector.windowResize = function(event)
+{
+    if (this.currentPanel)
+        this.currentPanel.resize();
+    this.drawer.resize();
+}
+
+WebInspector.windowFocused = function(event)
+{
+    // Fires after blur, so when focusing on either the main inspector
+    // or an <iframe> within the inspector we should always remove the
+    // "inactive" class.
+    if (event.target.document.nodeType === Node.DOCUMENT_NODE)
+        document.body.removeStyleClass("inactive");
+}
+
+WebInspector.windowBlurred = function(event)
+{
+    // Leaving the main inspector or an <iframe> within the inspector.
+    // We can add "inactive" now, and if we are moving the focus to another
+    // part of the inspector then windowFocused will correct this.
+    if (event.target.document.nodeType === Node.DOCUMENT_NODE)
+        document.body.addStyleClass("inactive");
+}
+
+WebInspector.focusChanged = function(event)
+{
+    this.currentFocusElement = event.target;
+}
+
+WebInspector.setAttachedWindow = function(attached)
+{
+    this.attached = attached;
+}
+
+WebInspector.close = function(event)
+{
+    if (this._isClosing)
+        return;
+    this._isClosing = true;
+    InspectorFrontendHost.closeWindow();
+}
+
+WebInspector.disconnectFromBackend = function()
+{
+    InspectorFrontendHost.disconnectFromBackend();
+}
+
+WebInspector.documentClick = function(event)
+{
+    var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
+    if (!anchor || anchor.target === "_blank")
+        return;
+
+    // Prevent the link from navigating, since we don't do any navigation by following links normally.
+    event.preventDefault();
+    event.stopPropagation();
+
+    function followLink()
+    {
+        // FIXME: support webkit-html-external-link links here.
+        if (WebInspector.canShowSourceLine(anchor.href, anchor.getAttribute("line_number"), anchor.getAttribute("preferred_panel"))) {
+            if (anchor.hasStyleClass("webkit-html-external-link")) {
+                anchor.removeStyleClass("webkit-html-external-link");
+                anchor.addStyleClass("webkit-html-resource-link");
+            }
+
+            WebInspector.showSourceLine(anchor.href, anchor.getAttribute("line_number"), anchor.getAttribute("preferred_panel"));
+            return;
+        }
+
+        const profileMatch = WebInspector.ProfileType.URLRegExp.exec(anchor.href);
+        if (profileMatch) {
+            WebInspector.showProfileForURL(anchor.href);
+            return;
+        }
+
+        var parsedURL = anchor.href.asParsedURL();
+        if (parsedURL && parsedURL.scheme === "webkit-link-action") {
+            if (parsedURL.host === "show-panel") {
+                var panel = parsedURL.path.substring(1);
+                if (WebInspector.panels[panel])
+                    WebInspector.showPanel(panel);
+            }
+            return;
+        }
+
+        WebInspector.showPanel("resources");
+    }
+
+    if (WebInspector.followLinkTimeout)
+        clearTimeout(WebInspector.followLinkTimeout);
+
+    if (anchor.preventFollowOnDoubleClick) {
+        // Start a timeout if this is the first click, if the timeout is canceled
+        // before it fires, then a double clicked happened or another link was clicked.
+        if (event.detail === 1)
+            WebInspector.followLinkTimeout = setTimeout(followLink, 333);
+        return;
+    }
+
+    followLink();
+}
+
+WebInspector.openResource = function(resourceURL, inResourcesPanel)
+{
+    var resource = WebInspector.resourceForURL(resourceURL);
+    if (inResourcesPanel && resource) {
+        WebInspector.panels.resources.showResource(resource);
+        WebInspector.showPanel("resources");
+    } else
+        InspectorBackend.openInInspectedWindow(resource ? resource.url : resourceURL);
+}
+
+WebInspector._registerShortcuts = function()
+{
+    var shortcut = WebInspector.KeyboardShortcut;
+    var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("All Panels"));
+    var keys = [
+        shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta),
+        shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta)
+    ];
+    section.addRelatedKeys(keys, WebInspector.UIString("Next/previous panel"));
+    section.addKey(shortcut.shortcutToString(shortcut.Keys.Esc), WebInspector.UIString("Toggle console"));
+    section.addKey(shortcut.shortcutToString("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search"));
+    if (WebInspector.isMac()) {
+        keys = [
+            shortcut.shortcutToString("g", shortcut.Modifiers.Meta),
+            shortcut.shortcutToString("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
+        ];
+        section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous"));
+    }
+}
+
+WebInspector.documentKeyDown = function(event)
+{
+    var isInputElement = event.target.nodeName === "INPUT";
+    var isInEditMode = event.target.enclosingNodeOrSelfWithClass("text-prompt") || WebInspector.isEditingAnyField();
+    const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; // "?" for both platforms
+
+    if (event.keyIdentifier === "F1" ||
+        (event.keyIdentifier === helpKey && event.shiftKey && (!isInEditMode && !isInputElement || event.metaKey))) {
+        WebInspector.shortcutsHelp.show();
+        event.stopPropagation();
+        event.preventDefault();
+        return;
+    }
+
+    if (WebInspector.isEditingAnyField())
+        return;
+
+    if (this.currentFocusElement && this.currentFocusElement.handleKeyEvent) {
+        this.currentFocusElement.handleKeyEvent(event);
+        if (event.handled) {
+            event.preventDefault();
+            return;
+        }
+    }
+
+    if (this.currentPanel && this.currentPanel.handleShortcut) {
+        this.currentPanel.handleShortcut(event);
+        if (event.handled) {
+            event.preventDefault();
+            return;
+        }
+    }
+
+    var isMac = WebInspector.isMac();
+    switch (event.keyIdentifier) {
+        case "Left":
+            var isBackKey = !isInEditMode && (isMac ? event.metaKey : event.ctrlKey);
+            if (isBackKey && this._panelHistory.canGoBack()) {
+                this._panelHistory.goBack();
+                event.preventDefault();
+            }
+            break;
+
+        case "Right":
+            var isForwardKey = !isInEditMode && (isMac ? event.metaKey : event.ctrlKey);
+            if (isForwardKey && this._panelHistory.canGoForward()) {
+                this._panelHistory.goForward();
+                event.preventDefault();
+            }
+            break;
+
+        case "U+001B": // Escape key
+            event.preventDefault();
+            if (this.drawer.fullPanel)
+                return;
+
+            this.drawer.visible = !this.drawer.visible;
+            break;
+
+        case "U+0046": // F key
+            if (isMac)
+                var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
+            else
+                var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
+
+            if (isFindKey) {
+                WebInspector.focusSearchField();
+                event.preventDefault();
+            }
+            break;
+
+        case "F3":
+            if (!isMac) {
+                WebInspector.focusSearchField();
+                event.preventDefault();
+            }
+            break;
+
+        case "U+0047": // G key
+            if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
+                if (event.shiftKey) {
+                    if (this.currentPanel.jumpToPreviousSearchResult)
+                        this.currentPanel.jumpToPreviousSearchResult();
+                } else if (this.currentPanel.jumpToNextSearchResult)
+                    this.currentPanel.jumpToNextSearchResult();
+                event.preventDefault();
+            }
+            break;
+
+        // Windows and Mac have two different definitions of [, so accept both.
+        case "U+005B":
+        case "U+00DB": // [ key
+            if (isMac)
+                var isRotateLeft = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
+            else
+                var isRotateLeft = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
+
+            if (isRotateLeft) {
+                var index = this.panelOrder.indexOf(this.currentPanel);
+                index = (index === 0) ? this.panelOrder.length - 1 : index - 1;
+                this.panelOrder[index].toolbarItem.click();
+                event.preventDefault();
+            }
+
+            break;
+
+        // Windows and Mac have two different definitions of ], so accept both.
+        case "U+005D":
+        case "U+00DD":  // ] key
+            if (isMac)
+                var isRotateRight = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
+            else
+                var isRotateRight = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
+
+            if (isRotateRight) {
+                var index = this.panelOrder.indexOf(this.currentPanel);
+                index = (index + 1) % this.panelOrder.length;
+                this.panelOrder[index].toolbarItem.click();
+                event.preventDefault();
+            }
+
+            break;
+
+        case "U+0052": // R key
+            if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
+                InspectorBackend.reloadPage(event.shiftKey);
+                event.preventDefault();
+            }
+            break;
+        case "F5":
+            if (!isMac)
+                InspectorBackend.reloadPage(event.ctrlKey || event.shiftKey);
+            break;
+    }
+}
+
+WebInspector.documentCanCopy = function(event)
+{
+    if (this.currentPanel && this.currentPanel.handleCopyEvent)
+        event.preventDefault();
+}
+
+WebInspector.documentCopy = function(event)
+{
+    if (this.currentPanel && this.currentPanel.handleCopyEvent)
+        this.currentPanel.handleCopyEvent(event);
+}
+
+WebInspector.contextMenuEventFired = function(event)
+{
+    if (event.handled || event.target.hasStyleClass("popup-glasspane"))
+        event.preventDefault();
+}
+
+WebInspector.animateStyle = function(animations, duration, callback)
+{
+    var interval;
+    var complete = 0;
+    var hasCompleted = false;
+
+    const intervalDuration = (1000 / 30); // 30 frames per second.
+    const animationsLength = animations.length;
+    const propertyUnit = {opacity: ""};
+    const defaultUnit = "px";
+
+    function cubicInOut(t, b, c, d)
+    {
+        if ((t/=d/2) < 1) return c/2*t*t*t + b;
+        return c/2*((t-=2)*t*t + 2) + b;
+    }
+
+    // Pre-process animations.
+    for (var i = 0; i < animationsLength; ++i) {
+        var animation = animations[i];
+        var element = null, start = null, end = null, key = null;
+        for (key in animation) {
+            if (key === "element")
+                element = animation[key];
+            else if (key === "start")
+                start = animation[key];
+            else if (key === "end")
+                end = animation[key];
+        }
+
+        if (!element || !end)
+            continue;
+
+        if (!start) {
+            var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element);
+            start = {};
+            for (key in end)
+                start[key] = parseInt(computedStyle.getPropertyValue(key));
+            animation.start = start;
+        } else
+            for (key in start)
+                element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+    }
+
+    function animateLoop()
+    {
+        // Advance forward.
+        complete += intervalDuration;
+        var next = complete + intervalDuration;
+
+        // Make style changes.
+        for (var i = 0; i < animationsLength; ++i) {
+            var animation = animations[i];
+            var element = animation.element;
+            var start = animation.start;
+            var end = animation.end;
+            if (!element || !end)
+                continue;
+
+            var style = element.style;
+            for (key in end) {
+                var endValue = end[key];
+                if (next < duration) {
+                    var startValue = start[key];
+                    var newValue = cubicInOut(complete, startValue, endValue - startValue, duration);
+                    style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+                } else
+                    style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+            }
+        }
+
+        // End condition.
+        if (complete >= duration) {
+            hasCompleted = true;
+            clearInterval(interval);
+            if (callback)
+                callback();
+        }
+    }
+
+    function forceComplete()
+    {
+        if (!hasCompleted) {
+            complete = duration;
+            animateLoop();
+        }
+    }
+
+    function cancel()
+    {
+        hasCompleted = true;
+        clearInterval(interval);
+    }
+
+    interval = setInterval(animateLoop, intervalDuration);
+    return {
+        cancel: cancel,
+        forceComplete: forceComplete
+    };
+}
+
+WebInspector.updateSearchLabel = function()
+{
+    if (!this.currentPanel)
+        return;
+
+    var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
+    if (this.attached)
+        document.getElementById("search").setAttribute("placeholder", newLabel);
+    else {
+        document.getElementById("search").removeAttribute("placeholder");
+        document.getElementById("search-toolbar-label").textContent = newLabel;
+    }
+}
+
+WebInspector.focusSearchField = function()
+{
+    var searchField = document.getElementById("search");
+    searchField.focus();
+    searchField.select();
+}
+
+WebInspector.toggleAttach = function()
+{
+    if (!this.attached)
+        InspectorFrontendHost.requestAttachWindow();
+    else
+        InspectorFrontendHost.requestDetachWindow();
+}
+
+WebInspector.toolbarDragStart = function(event)
+{
+    if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
+        return;
+
+    var target = event.target;
+    if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
+        return;
+
+    var toolbar = document.getElementById("toolbar");
+    if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
+        return;
+
+    toolbar.lastScreenX = event.screenX;
+    toolbar.lastScreenY = event.screenY;
+
+    WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
+}
+
+WebInspector.toolbarDragEnd = function(event)
+{
+    var toolbar = document.getElementById("toolbar");
+
+    WebInspector.elementDragEnd(event);
+
+    delete toolbar.lastScreenX;
+    delete toolbar.lastScreenY;
+}
+
+WebInspector.toolbarDrag = function(event)
+{
+    var toolbar = document.getElementById("toolbar");
+
+    if (WebInspector.attached) {
+        var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
+
+        InspectorFrontendHost.setAttachedWindowHeight(height);
+    } else {
+        var x = event.screenX - toolbar.lastScreenX;
+        var y = event.screenY - toolbar.lastScreenY;
+
+        // We cannot call window.moveBy here because it restricts the movement
+        // of the window at the edges.
+        InspectorFrontendHost.moveWindowBy(x, y);
+    }
+
+    toolbar.lastScreenX = event.screenX;
+    toolbar.lastScreenY = event.screenY;
+
+    event.preventDefault();
+}
+
+WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
+{
+    if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
+        this.elementDragEnd(event);
+
+    this._elementDraggingEventListener = dividerDrag;
+    this._elementEndDraggingEventListener = elementDragEnd;
+
+    document.addEventListener("mousemove", dividerDrag, true);
+    document.addEventListener("mouseup", elementDragEnd, true);
+
+    document.body.style.cursor = cursor;
+
+    event.preventDefault();
+}
+
+WebInspector.elementDragEnd = function(event)
+{
+    document.removeEventListener("mousemove", this._elementDraggingEventListener, true);
+    document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true);
+
+    document.body.style.removeProperty("cursor");
+
+    delete this._elementDraggingEventListener;
+    delete this._elementEndDraggingEventListener;
+
+    event.preventDefault();
+}
+
+WebInspector.toggleSearchingForNode = function()
+{
+    if (this.panels.elements) {
+        this.showPanel("elements");
+        this.panels.elements.toggleSearchingForNode();
+    }
+}
+
+WebInspector.showConsole = function()
+{
+    this.drawer.showView(this.console);
+}
+
+WebInspector.showPanel = function(panel)
+{
+    if (!(panel in this.panels))
+        panel = "elements";
+    this.currentPanel = this.panels[panel];
+}
+
+WebInspector.domContentEventFired = function(time)
+{
+    this.panels.audits.mainResourceDOMContentTime = time;
+    if (this.panels.network)
+        this.panels.network.mainResourceDOMContentTime = time;
+    this.extensionServer.notifyPageDOMContentLoaded((time - WebInspector.mainResource.startTime) * 1000);
+    this.mainResourceDOMContentTime = time;
+}
+
+WebInspector.loadEventFired = function(time)
+{
+    this.panels.audits.mainResourceLoadTime = time;
+    this.panels.network.mainResourceLoadTime = time;
+    this.panels.resources.loadEventFired();
+    this.extensionServer.notifyPageLoaded((time - WebInspector.mainResource.startTime) * 1000);
+    this.mainResourceLoadTime = time;
+}
+
+WebInspector.searchingForNodeWasEnabled = function()
+{
+    this.panels.elements.searchingForNodeWasEnabled();
+}
+
+WebInspector.searchingForNodeWasDisabled = function()
+{
+    this.panels.elements.searchingForNodeWasDisabled();
+}
+
+WebInspector.reset = function()
+{
+    this.debuggerModel.reset();
+
+    for (var panelName in this.panels) {
+        var panel = this.panels[panelName];
+        if ("reset" in panel)
+            panel.reset();
+    }
+
+    this.resources = {};
+    this.highlightDOMNode(0);
+
+    this.console.clearMessages();
+    this.extensionServer.notifyInspectorReset();
+}
+
+WebInspector.bringToFront = function()
+{
+    InspectorFrontendHost.bringToFront();
+}
+
+WebInspector.inspectedURLChanged = function(url)
+{
+    InspectorFrontendHost.inspectedURLChanged(url);
+    this.settings.inspectedURLChanged(url);
+    this.extensionServer.notifyInspectedURLChanged();
+}
+
+WebInspector.log = function(message, messageLevel)
+{
+    // remember 'this' for setInterval() callback
+    var self = this;
+
+    // return indication if we can actually log a message
+    function isLogAvailable()
+    {
+        return WebInspector.ConsoleMessage && WebInspector.RemoteObject && self.console;
+    }
+
+    // flush the queue of pending messages
+    function flushQueue()
+    {
+        var queued = WebInspector.log.queued;
+        if (!queued)
+            return;
+
+        for (var i = 0; i < queued.length; ++i)
+            logMessage(queued[i]);
+
+        delete WebInspector.log.queued;
+    }
+
+    // flush the queue if it console is available
+    // - this function is run on an interval
+    function flushQueueIfAvailable()
+    {
+        if (!isLogAvailable())
+            return;
+
+        clearInterval(WebInspector.log.interval);
+        delete WebInspector.log.interval;
+
+        flushQueue();
+    }
+
+    // actually log the message
+    function logMessage(message)
+    {
+        var repeatCount = 1;
+        if (message == WebInspector.log.lastMessage)
+            repeatCount = WebInspector.log.repeatCount + 1;
+
+        WebInspector.log.lastMessage = message;
+        WebInspector.log.repeatCount = repeatCount;
+
+        // ConsoleMessage expects a proxy object
+        message = new WebInspector.RemoteObject.fromPrimitiveValue(message);
+
+        // post the message
+        var msg = new WebInspector.ConsoleMessage(
+            WebInspector.ConsoleMessage.MessageSource.Other,
+            WebInspector.ConsoleMessage.MessageType.Log,
+            messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug,
+            -1,
+            null,
+            repeatCount,
+            null,
+            [message],
+            null);
+
+        self.console.addMessage(msg);
+    }
+
+    // if we can't log the message, queue it
+    if (!isLogAvailable()) {
+        if (!WebInspector.log.queued)
+            WebInspector.log.queued = [];
+
+        WebInspector.log.queued.push(message);
+
+        if (!WebInspector.log.interval)
+            WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000);
+
+        return;
+    }
+
+    // flush the pending queue if any
+    flushQueue();
+
+    // log the message
+    logMessage(message);
+}
+
+WebInspector.drawLoadingPieChart = function(canvas, percent) {
+    var g = canvas.getContext("2d");
+    var darkColor = "rgb(122, 168, 218)";
+    var lightColor = "rgb(228, 241, 251)";
+    var cx = 8;
+    var cy = 8;
+    var r = 7;
+
+    g.beginPath();
+    g.arc(cx, cy, r, 0, Math.PI * 2, false);
+    g.closePath();
+
+    g.lineWidth = 1;
+    g.strokeStyle = darkColor;
+    g.fillStyle = lightColor;
+    g.fill();
+    g.stroke();
+
+    var startangle = -Math.PI / 2;
+    var endangle = startangle + (percent * Math.PI * 2);
+
+    g.beginPath();
+    g.moveTo(cx, cy);
+    g.arc(cx, cy, r, startangle, endangle, false);
+    g.closePath();
+
+    g.fillStyle = darkColor;
+    g.fill();
+}
+
+WebInspector.updateFocusedNode = function(nodeId)
+{
+    this._updateFocusedNode(nodeId);
+    this.highlightDOMNodeForTwoSeconds(nodeId);
+}
+
+WebInspector.displayNameForURL = function(url)
+{
+    if (!url)
+        return "";
+
+    var resource = this.resourceForURL(url);
+    if (resource)
+        return resource.displayName;
+
+    if (!WebInspector.mainResource)
+        return url.trimURL("");
+
+    var lastPathComponent = WebInspector.mainResource.lastPathComponent;
+    var index = WebInspector.mainResource.url.indexOf(lastPathComponent);
+    if (index !== -1 && index + lastPathComponent.length === WebInspector.mainResource.url.length) {
+        var baseURL = WebInspector.mainResource.url.substring(0, index);
+        if (url.indexOf(baseURL) === 0)
+            return url.substring(index);
+    }
+
+    return url.trimURL(WebInspector.mainResource.domain);
+}
+
+WebInspector._choosePanelToShowSourceLine = function(url, line, preferredPanel)
+{
+    preferredPanel = preferredPanel || "resources";
+
+    var panel = this.panels[preferredPanel];
+    if (panel && panel.canShowSourceLine(url, line))
+        return panel;
+    panel = this.panels.resources;
+    return panel.canShowSourceLine(url, line) ? panel : null;
+}
+
+WebInspector.canShowSourceLine = function(url, line, preferredPanel)
+{
+    return !!this._choosePanelToShowSourceLine(url, line, preferredPanel);
+}
+
+WebInspector.showSourceLine = function(url, line, preferredPanel)
+{
+    this.currentPanel = this._choosePanelToShowSourceLine(url, line, preferredPanel);
+    if (!this.currentPanel)
+        return false;
+    if (this.drawer)
+        this.drawer.immediatelyFinishAnimation();
+    this.currentPanel.showSourceLine(url, line);
+    return true;
+}
+
+WebInspector.linkifyStringAsFragment = function(string)
+{
+    var container = document.createDocumentFragment();
+    var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/;
+    var lineColumnRegEx = /:(\d+)(:(\d+))?$/;
+
+    while (string) {
+        var linkString = linkStringRegEx.exec(string);
+        if (!linkString)
+            break;
+
+        linkString = linkString[0];
+        var title = linkString;
+        var linkIndex = string.indexOf(linkString);
+        var nonLink = string.substring(0, linkIndex);
+        container.appendChild(document.createTextNode(nonLink));
+
+        var profileStringMatches = WebInspector.ProfileType.URLRegExp.exec(title);
+        if (profileStringMatches)
+            title = WebInspector.panels.profiles.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]);
+
+        var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString);
+        var lineColumnMatch = lineColumnRegEx.exec(realURL);
+        if (lineColumnMatch)
+            realURL = realURL.substring(0, realURL.length - lineColumnMatch[0].length);
+
+        var hasResourceWithURL = !!WebInspector.resourceForURL(realURL);
+        var urlNode = WebInspector.linkifyURLAsNode(realURL, title, null, hasResourceWithURL);
+        container.appendChild(urlNode);
+        if (lineColumnMatch) {
+            urlNode.setAttribute("line_number", lineColumnMatch[1]);
+            urlNode.setAttribute("preferred_panel", "scripts");
+        }
+        string = string.substring(linkIndex + linkString.length, string.length);
+    }
+
+    if (string)
+        container.appendChild(document.createTextNode(string));
+
+    return container;
+}
+
+WebInspector.showProfileForURL = function(url)
+{
+    WebInspector.showPanel("profiles");
+    WebInspector.panels.profiles.showProfileForURL(url);
+}
+
+WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText)
+{
+    if (!linkText)
+        linkText = url;
+    classes = (classes ? classes + " " : "");
+    classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link";
+
+    var a = document.createElement("a");
+    a.href = url;
+    a.className = classes;
+    if (typeof tooltipText === "undefined")
+        a.title = url;
+    else if (typeof tooltipText !== "string" || tooltipText.length)
+        a.title = tooltipText;
+    a.textContent = linkText;
+
+    return a;
+}
+
+WebInspector.linkifyURL = function(url, linkText, classes, isExternal, tooltipText)
+{
+    // Use the DOM version of this function so as to avoid needing to escape attributes.
+    // FIXME:  Get rid of linkifyURL entirely.
+    return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal, tooltipText).outerHTML;
+}
+
+WebInspector.linkifyResourceAsNode = function(url, preferredPanel, lineNumber, classes, tooltipText)
+{
+    var linkText = WebInspector.displayNameForURL(url);
+    if (lineNumber)
+        linkText += ":" + lineNumber;
+    var node = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText);
+    node.setAttribute("line_number", lineNumber);
+    node.setAttribute("preferred_panel", preferredPanel);
+    return node;
+}
+
+WebInspector.resourceURLForRelatedNode = function(node, url)
+{
+    if (!url || url.indexOf("://") > 0)
+        return url;
+
+    for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
+        if (frameOwnerCandidate.documentURL) {
+            var result = WebInspector.completeURL(frameOwnerCandidate.documentURL, url);
+            if (result)
+                return result;
+            break;
+        }
+    }
+
+    // documentURL not found or has bad value
+    var resourceURL = url;
+    function callback(resource)
+    {
+        if (resource.path === url) {
+            resourceURL = resource.url;
+            return true;
+        }
+    }
+    WebInspector.forAllResources(callback);
+    return resourceURL;
+}
+
+WebInspector.completeURL = function(baseURL, href)
+{
+    if (href) {
+        // Return absolute URLs as-is.
+        var parsedHref = href.asParsedURL();
+        if (parsedHref && parsedHref.scheme)
+            return href;
+    }
+
+    var parsedURL = baseURL.asParsedURL();
+    if (parsedURL) {
+        var path = href;
+        if (path.charAt(0) !== "/") {
+            var basePath = parsedURL.path;
+            // A href of "?foo=bar" implies "basePath?foo=bar".
+            // With "basePath?a=b" and "?foo=bar" we should get "basePath?foo=bar".
+            var prefix;
+            if (path.charAt(0) === "?") {
+                var basePathCutIndex = basePath.indexOf("?");
+                if (basePathCutIndex !== -1)
+                    prefix = basePath.substring(0, basePathCutIndex);
+                else
+                    prefix = basePath;
+            } else
+                prefix = basePath.substring(0, basePath.lastIndexOf("/")) + "/";
+
+            path = prefix + path;
+        } else if (path.length > 1 && path.charAt(1) === "/") {
+            // href starts with "//" which is a full URL with the protocol dropped (use the baseURL protocol).
+            return parsedURL.scheme + ":" + path;
+        }
+        return parsedURL.scheme + "://" + parsedURL.host + (parsedURL.port ? (":" + parsedURL.port) : "") + path;
+    }
+    return null;
+}
+
+WebInspector.addMainEventListeners = function(doc)
+{
+    doc.defaultView.addEventListener("focus", this.windowFocused.bind(this), false);
+    doc.defaultView.addEventListener("blur", this.windowBlurred.bind(this), false);
+    doc.addEventListener("click", this.documentClick.bind(this), true);
+}
+
+WebInspector._searchFieldManualFocus = function(event)
+{
+    this.currentFocusElement = event.target;
+    this._previousFocusElement = event.target;
+}
+
+WebInspector._searchKeyDown = function(event)
+{
+    // Escape Key will clear the field and clear the search results
+    if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+        // If focus belongs here and text is empty - nothing to do, return unhandled.
+        if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
+            return;
+        event.preventDefault();
+        event.stopPropagation();
+        // When search was selected manually and is currently blank, we'd like Esc stay unhandled
+        // and hit console drawer handler.
+        event.target.value = "";
+
+        this.performSearch(event);
+        this.currentFocusElement = this.previousFocusElement;
+        if (this.currentFocusElement === event.target)
+            this.currentFocusElement.select();
+        return false;
+    }
+
+    if (!isEnterKey(event))
+        return false;
+
+    // Select all of the text so the user can easily type an entirely new query.
+    event.target.select();
+
+    // Only call performSearch if the Enter key was pressed. Otherwise the search
+    // performance is poor because of searching on every key. The search field has
+    // the incremental attribute set, so we still get incremental searches.
+    this.performSearch(event);
+
+    // Call preventDefault since this was the Enter key. This prevents a "search" event
+    // from firing for key down. This stops performSearch from being called twice in a row.
+    event.preventDefault();
+}
+
+WebInspector.performSearch = function(event)
+{
+    var forceSearch = event.keyIdentifier === "Enter";
+    this.doPerformSearch(event.target.value, forceSearch, event.shiftKey, false);
+}
+
+WebInspector.cancelSearch = function()
+{
+    document.getElementById("search").value = "";
+    this.doPerformSearch("");
+}
+
+WebInspector.doPerformSearch = function(query, forceSearch, isBackwardSearch, repeatSearch)
+{
+    var isShortSearch = (query.length < 3);
+
+    // Clear a leftover short search flag due to a non-conflicting forced search.
+    if (isShortSearch && this.shortSearchWasForcedByKeyEvent && this.currentQuery !== query)
+        delete this.shortSearchWasForcedByKeyEvent;
+
+    // Indicate this was a forced search on a short query.
+    if (isShortSearch && forceSearch)
+        this.shortSearchWasForcedByKeyEvent = true;
+
+    if (!query || !query.length || (!forceSearch && isShortSearch)) {
+        // Prevent clobbering a short search forced by the user.
+        if (this.shortSearchWasForcedByKeyEvent) {
+            delete this.shortSearchWasForcedByKeyEvent;
+            return;
+        }
+
+        delete this.currentQuery;
+
+        for (var panelName in this.panels) {
+            var panel = this.panels[panelName];
+            var hadCurrentQuery = !!panel.currentQuery;
+            delete panel.currentQuery;
+            if (hadCurrentQuery && panel.searchCanceled)
+                panel.searchCanceled();
+        }
+
+        this.updateSearchMatchesCount();
+
+        return;
+    }
+
+    if (!repeatSearch && query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
+        // When this is the same query and a forced search, jump to the next
+        // search result for a good user experience.
+        if (forceSearch) {
+            if (!isBackwardSearch && this.currentPanel.jumpToNextSearchResult)
+                this.currentPanel.jumpToNextSearchResult();
+            else if (isBackwardSearch && this.currentPanel.jumpToPreviousSearchResult)
+                this.currentPanel.jumpToPreviousSearchResult();
+        }
+        return;
+    }
+
+    this.currentQuery = query;
+
+    this.updateSearchMatchesCount();
+
+    if (!this.currentPanel.performSearch)
+        return;
+
+    this.currentPanel.currentQuery = query;
+    this.currentPanel.performSearch(query);
+}
+
+WebInspector.frontendReused = function()
+{
+    this.networkManager.reset();
+    this.reset();
+}
+
+WebInspector.addNodesToSearchResult = function(nodeIds)
+{
+    WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
+}
+
+WebInspector.updateSearchMatchesCount = function(matches, panel)
+{
+    if (!panel)
+        panel = this.currentPanel;
+
+    panel.currentSearchMatches = matches;
+
+    if (panel !== this.currentPanel)
+        return;
+
+    if (!this.currentPanel.currentQuery) {
+        document.getElementById("search-results-matches").addStyleClass("hidden");
+        return;
+    }
+
+    if (matches) {
+        if (matches === 1)
+            var matchesString = WebInspector.UIString("1 match");
+        else
+            var matchesString = WebInspector.UIString("%d matches", matches);
+    } else
+        var matchesString = WebInspector.UIString("Not Found");
+
+    var matchesToolbarElement = document.getElementById("search-results-matches");
+    matchesToolbarElement.removeStyleClass("hidden");
+    matchesToolbarElement.textContent = matchesString;
+}
+
+WebInspector.UIString = function(string)
+{
+    if (window.localizedStrings && string in window.localizedStrings)
+        string = window.localizedStrings[string];
+    else {
+        if (!(string in WebInspector.missingLocalizedStrings)) {
+            if (!WebInspector.InspectorBackendStub)
+                console.error("Localized string \"" + string + "\" not found.");
+            WebInspector.missingLocalizedStrings[string] = true;
+        }
+
+        if (Preferences.showMissingLocalizedStrings)
+            string += " (not localized)";
+    }
+
+    return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
+}
+
+WebInspector.formatLocalized = function(format, substitutions, formatters, initialValue, append)
+{
+    return String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append);
+}
+
+WebInspector.isMac = function()
+{
+    if (!("_isMac" in this))
+        this._isMac = WebInspector.platform === "mac";
+
+    return this._isMac;
+}
+
+WebInspector.isBeingEdited = function(element)
+{
+    return element.__editing;
+}
+
+WebInspector.isEditingAnyField = function()
+{
+    return this.__editing;
+}
+
+// Available config fields (all optional):
+// context: Object - an arbitrary context object to be passed to the commit and cancel handlers
+// commitHandler: Function - handles editing "commit" outcome
+// cancelHandler: Function - handles editing "cancel" outcome
+// customFinishHandler: Function - custom finish handler for the editing session (invoked on keydown)
+// pasteHandler: Function - handles the "paste" event, return values are the same as those for customFinishHandler
+// multiline: Boolean - whether the edited element is multiline
+WebInspector.startEditing = function(element, config)
+{
+    if (element.__editing)
+        return;
+    element.__editing = true;
+    WebInspector.__editing = true;
+
+    config = config || {};
+    var committedCallback = config.commitHandler;
+    var cancelledCallback = config.cancelHandler;
+    var pasteCallback = config.pasteHandler;
+    var context = config.context;
+    var oldText = getContent(element);
+    var moveDirection = "";
+
+    element.addStyleClass("editing");
+
+    var oldTabIndex = element.tabIndex;
+    if (element.tabIndex < 0)
+        element.tabIndex = 0;
+
+    function blurEventListener() {
+        editingCommitted.call(element);
+    }
+
+    function getContent(element) {
+        if (element.tagName === "INPUT" && element.type === "text")
+            return element.value;
+        else
+            return element.textContent;
+    }
+
+    function cleanUpAfterEditing() {
+        delete this.__editing;
+        delete WebInspector.__editing;
+
+        this.removeStyleClass("editing");
+        this.tabIndex = oldTabIndex;
+        this.scrollTop = 0;
+        this.scrollLeft = 0;
+
+        element.removeEventListener("blur", blurEventListener, false);
+        element.removeEventListener("keydown", keyDownEventListener, true);
+        if (pasteCallback)
+            element.removeEventListener("paste", pasteEventListener, true);
+
+        if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement))
+            WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+    }
+
+    function editingCancelled() {
+        if (this.tagName === "INPUT" && this.type === "text")
+            this.value = oldText;
+        else
+            this.textContent = oldText;
+
+        cleanUpAfterEditing.call(this);
+
+        if (cancelledCallback)
+            cancelledCallback(this, context);
+    }
+
+    function editingCommitted() {
+        cleanUpAfterEditing.call(this);
+
+        if (committedCallback)
+            committedCallback(this, getContent(this), oldText, context, moveDirection);
+    }
+
+    function defaultFinishHandler(event)
+    {
+        var isMetaOrCtrl = WebInspector.isMac() ?
+            event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey :
+            event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
+        if (isEnterKey(event) && (!config.multiline || isMetaOrCtrl))
+            return "commit";
+        else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
+            return "cancel";
+        else if (event.keyIdentifier === "U+0009") // Tab key
+            return "move-" + (event.shiftKey ? "backward" : "forward");
+    }
+
+    function handleEditingResult(result, event)
+    {
+        if (result === "commit") {
+            editingCommitted.call(element);
+            event.preventDefault();
+            event.stopPropagation();
+        } else if (result === "cancel") {
+            editingCancelled.call(element);
+            event.preventDefault();
+            event.stopPropagation();
+        } else if (result && result.indexOf("move-") === 0) {
+            moveDirection = result.substring(5);
+            if (event.keyIdentifier !== "U+0009")
+                blurEventListener();
+        }
+    }
+
+    function pasteEventListener(event)
+    {
+        var result = pasteCallback(event);
+        handleEditingResult(result, event);
+    }
+
+    function keyDownEventListener(event)
+    {
+        var handler = config.customFinishHandler || defaultFinishHandler;
+        var result = handler(event);
+        handleEditingResult(result, event);
+    }
+
+    element.addEventListener("blur", blurEventListener, false);
+    element.addEventListener("keydown", keyDownEventListener, true);
+    if (pasteCallback)
+        element.addEventListener("paste", pasteEventListener, true);
+
+    WebInspector.currentFocusElement = element;
+    return {
+        cancel: editingCancelled.bind(element),
+        commit: editingCommitted.bind(element)
+    };
+}
+
+WebInspector._toolbarItemClicked = function(event)
+{
+    var toolbarItem = event.currentTarget;
+    this.currentPanel = toolbarItem.panel;
+}
+
+// This table maps MIME types to the Resource.Types which are valid for them.
+// The following line:
+//    "text/html":                {0: 1},
+// means that text/html is a valid MIME type for resources that have type
+// WebInspector.Resource.Type.Document (which has a value of 0).
+WebInspector.MIMETypes = {
+    "text/html":                   {0: true},
+    "text/xml":                    {0: true},
+    "text/plain":                  {0: true},
+    "application/xhtml+xml":       {0: true},
+    "text/css":                    {1: true},
+    "text/xsl":                    {1: true},
+    "image/jpeg":                  {2: true},
+    "image/png":                   {2: true},
+    "image/gif":                   {2: true},
+    "image/bmp":                   {2: true},
+    "image/vnd.microsoft.icon":    {2: true},
+    "image/x-icon":                {2: true},
+    "image/x-xbitmap":             {2: true},
+    "font/ttf":                    {3: true},
+    "font/opentype":               {3: true},
+    "application/x-font-type1":    {3: true},
+    "application/x-font-ttf":      {3: true},
+    "application/x-font-woff":     {3: true},
+    "application/x-truetype-font": {3: true},
+    "text/javascript":             {4: true},
+    "text/ecmascript":             {4: true},
+    "application/javascript":      {4: true},
+    "application/ecmascript":      {4: true},
+    "application/x-javascript":    {4: true},
+    "text/javascript1.1":          {4: true},
+    "text/javascript1.2":          {4: true},
+    "text/javascript1.3":          {4: true},
+    "text/jscript":                {4: true},
+    "text/livescript":             {4: true},
+}
+
+WebInspector.PanelHistory = function()
+{
+    this._history = [];
+    this._historyIterator = -1;
+}
+
+WebInspector.PanelHistory.prototype = {
+    canGoBack: function()
+    {
+        return this._historyIterator > 0;
+    },
+
+    goBack: function()
+    {
+        this._inHistory = true;
+        WebInspector.currentPanel = WebInspector.panels[this._history[--this._historyIterator]];
+        delete this._inHistory;
+    },
+
+    canGoForward: function()
+    {
+        return this._historyIterator < this._history.length - 1;
+    },
+
+    goForward: function()
+    {
+        this._inHistory = true;
+        WebInspector.currentPanel = WebInspector.panels[this._history[++this._historyIterator]];
+        delete this._inHistory;
+    },
+
+    setPanel: function(panelName)
+    {
+        if (this._inHistory)
+            return;
+
+        this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1);
+        if (!this._history.length || this._history[this._history.length - 1] !== panelName)
+            this._history.push(panelName);
+        this._historyIterator = this._history.length - 1;
+    }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspectorSyntaxHighlight.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspectorSyntaxHighlight.css
new file mode 100644
index 0000000..0965a5c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/inspectorSyntaxHighlight.css
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.webkit-css-comment { 
+    color: rgb(0, 116, 0);
+}
+
+.webkit-css-url, .webkit-css-color, .webkit-css-string, .webkit-css-keyword {
+    color: rgb(7, 144, 154);
+ }
+
+.webkit-css-number {
+    color: rgb(50, 0, 255);
+}
+
+.webkit-css-property, .webkit-css-at-rule {
+    color: rgb(200, 0, 0);
+}
+
+.webkit-css-selector {
+    color: black;
+}
+
+.webkit-css-important {
+    color: rgb(200, 0, 180);
+}
+
+.webkit-javascript-comment {
+    color: rgb(0, 116, 0);
+}
+
+.webkit-javascript-keyword {
+    color: rgb(170, 13, 145);
+}
+
+.webkit-javascript-number {
+    color: rgb(28, 0, 207);
+}
+
+.webkit-javascript-string, .webkit-javascript-regexp {
+    color: rgb(196, 26, 22);
+}
+
+.webkit-javascript-ident {
+    color: black;
+}
+
+.webkit-html-comment {
+    /* Keep this in sync with view-source.css (.webkit-html-comment) */
+    color: rgb(35, 110, 37);
+}
+
+.webkit-html-tag {
+    /* Keep this in sync with view-source.css (.webkit-html-tag) */
+    color: rgb(136, 18, 128);
+}
+
+.webkit-html-doctype {
+    /* Keep this in sync with view-source.css (.webkit-html-doctype) */
+    color: rgb(192, 192, 192);
+}
+
+.webkit-html-attribute-name {
+    /* Keep this in sync with view-source.css (.webkit-html-attribute-name) */
+    color: rgb(153, 69, 0);
+}
+
+.webkit-html-attribute-value {
+    /* Keep this in sync with view-source.css (.webkit-html-attribute-value) */
+    color: rgb(26, 26, 166);
+}
+
+.webkit-html-external-link, .webkit-html-resource-link {
+    /* Keep this in sync with view-source.css (.webkit-html-external-link, .webkit-html-resource-link) */
+    color: #00e;
+}
+
+.webkit-html-external-link {
+    /* Keep this in sync with view-source.css (.webkit-html-external-link) */
+    text-decoration: none;
+}
+
+.webkit-html-external-link:hover {
+    /* Keep this in sync with view-source.css (.webkit-html-external-link:hover) */
+    text-decoration: underline;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/networkPanel.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/networkPanel.css
new file mode 100644
index 0000000..c750323
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/networkPanel.css
@@ -0,0 +1,821 @@
+.network-larger-resources-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
+}
+
+.network-sidebar .data-grid {
+    border: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    font-size: 11px;
+}
+
+.network-sidebar .data-grid table.data {
+    -webkit-background-size: 1px 82px;
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0.05)), to(rgba(0, 0, 0, 0.05)));
+    font-size: 11px;
+}
+
+.network-sidebar .data-grid.small table.data {
+    -webkit-background-size: 1px 42px;
+}
+
+.network-sidebar .data-grid td:not(.network-summary) {
+    line-height: 17px;
+    height: 37px;
+    border-right: 1px solid rgb(210, 210, 210);
+    vertical-align: middle;
+}
+
+.network-sidebar .data-grid.small td {
+    height: 17px;
+}
+
+.network-sidebar .data-grid th {
+    border-bottom: 1px solid rgb(64%, 64%, 64%);
+    height: 30px;
+    font-size: 11px;
+    font-weight: bold;
+}
+
+.network-sidebar .data-grid.small th {
+    height: 22px;
+}
+
+.network-sidebar .data-grid th, .network.panel .data-grid th.sort-descending, .network.panel .data-grid th.sort-ascending {
+    background: -webkit-gradient(linear, left top, left bottom, from(rgb(236, 236, 236)), to(rgb(217, 217, 217)));
+}
+
+.network-sidebar .data-grid .data-container {
+    top: 31px;
+}
+
+.network-sidebar .data-grid.small .data-container {
+    top: 23px;
+}
+
+.network-sidebar .data-grid select {
+    -webkit-appearance: none;
+    background-color: transparent;
+    border: none;
+    width: 100%;
+    font-size: 11px;
+    font-weight: bold;
+}
+
+.network-sidebar .data-grid.small tr.offscreen {
+    height: 21px;
+}
+
+.network-sidebar .data-grid tr.offscreen {
+    height: 41px;
+}
+
+.network-sidebar .data-grid tr.offscreen td {
+    display: none;
+}
+
+.network-sidebar .data-grid tr.filler {
+    background-color: white;
+}
+
+.network-sidebar .data-grid td.name-column {
+    font-weight: bold;
+    cursor: pointer;
+}
+
+.network.panel:not(.viewing-resource) .network-sidebar td.name-column:hover {
+    text-decoration: underline;
+}
+
+.network-sidebar .data-grid td.method-column,
+.network-sidebar .data-grid td.status-column,
+.network-sidebar .data-grid td.type-column,
+.network-sidebar .data-grid td.size-column,
+.network-sidebar .data-grid td.time-column {
+    background-color: rgba(0, 0, 0, 0.07);
+}
+
+.network-sidebar .data-grid td.size-column,
+.network-sidebar .data-grid td.time-column {
+    text-align: right;
+}
+
+.network-sidebar .small .network-graph-side {
+    height: 14px;
+}
+
+.network-sidebar .data-grid th.sortable:active {
+    background-image: none;
+}
+
+.network-cell-subtitle {
+    font-weight: normal;
+    color: gray;
+}
+
+.network-sidebar tr.selected .network-cell-subtitle {
+    color: white;
+}
+
+.network-header-subtitle {
+    color: gray;
+}
+
+.network-sidebar .data-grid.small .network-cell-subtitle,
+.network-sidebar .data-grid.small .network-header-subtitle
+{
+    display: none;
+}
+
+/* Resource preview icons */
+
+.network-sidebar .data-grid .icon {
+    content: url(Images/resourcePlainIcon.png);
+}
+
+.network-sidebar .data-grid.small .icon {
+    content: url(Images/resourcePlainIconSmall.png);
+}
+
+.network-sidebar .network-category-scripts .icon {
+    content: url(Images/resourceJSIcon.png);
+}
+
+.network-sidebar .data-grid.small .network-category-scripts .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network-sidebar .network-category-documents .icon {
+    content: url(Images/resourceDocumentIcon.png);
+}
+
+.network-sidebar .data-grid.small .network-category-documents .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network-sidebar .network-category-stylesheets .icon {
+    content: url(Images/resourceCSSIcon.png);
+}
+
+.network-sidebar .data-grid.small .network-category-stylesheets .icon {
+    content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network-sidebar .network-category-images .icon {
+    position: relative;
+    background-image: url(Images/resourcePlainIcon.png);
+    background-repeat: no-repeat;
+    content: "";
+}
+
+.network-sidebar .data-grid.small .network-category-images .icon {
+    background-image: url(Images/resourcePlainIconSmall.png);
+    content: "";
+}
+
+.network-sidebar .data-grid .icon {
+    float: left;
+    width: 32px;
+    height: 32px;
+    margin-top: 1px;
+    margin-right: 3px;
+}
+
+.network-sidebar .data-grid.small .icon {
+    width: 16px;
+    height: 16px;
+}
+
+.network-sidebar .image-network-icon-preview {
+    position: absolute;
+    margin: auto;
+    top: 3px;
+    bottom: 4px;
+    left: 5px;
+    right: 5px;
+    max-width: 18px;
+    max-height: 21px;
+    min-width: 1px;
+    min-height: 1px;
+}
+
+.network-sidebar .data-grid.small .image-network-icon-preview {
+    top: 2px;
+    bottom: 1px;
+    left: 3px;
+    right: 3px;
+    max-width: 8px;
+    max-height: 11px;
+}
+
+/* Graph styles */
+
+.network-graph-side {
+    position: relative;
+    height: 36px;
+    padding: 0 5px;
+    white-space: nowrap;
+    margin-top: 1px;
+    border-top: 1px solid transparent;
+    overflow: hidden;
+}
+
+.network-graph-bar-area {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 8px;
+    left: 9px;
+}
+
+.network-graph-label {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto -7px;
+    height: 13px;
+    line-height: 13px;
+    font-size: 9px;
+    color: rgba(0, 0, 0, 0.75);
+    text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
+    z-index: 150;
+    overflow: hidden;
+    text-align: center;
+    font-weight: bold;
+    opacity: 0;
+    -webkit-transition: opacity 250ms ease-in-out;
+}
+
+.network-graph-side:hover .network-graph-label {
+    opacity: 1;
+}
+
+.network-graph-label:empty {
+    display: none;
+}
+
+.network-graph-label.waiting {
+    margin-right: 5px;
+}
+
+.network-graph-label.waiting-right {
+    margin-left: 5px;
+}
+
+.network-graph-label.before {
+    color: rgba(0, 0, 0, 0.7);
+    text-shadow: none;
+    text-align: right;
+    margin-right: 2px;
+}
+
+.network-graph-label.before::after {
+    padding-left: 2px;
+    height: 6px;
+    content: url(Images/graphLabelCalloutLeft.png);
+}
+
+.network-graph-label.after {
+    color: rgba(0, 0, 0, 0.7);
+    text-shadow: none;
+    text-align: left;
+    margin-left: 2px;
+}
+
+.network-graph-label.after::before {
+    padding-right: 2px;
+    height: 6px;
+    content: url(Images/graphLabelCalloutRight.png);
+}
+
+.network-graph-bar {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto -7px;
+    border-width: 6px 7px;
+    height: 13px;
+    min-width: 14px;
+    opacity: 0.65;
+    -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.network-graph-bar.waiting, .network-graph-bar.waiting-right {
+    opacity: 0.35;
+}
+
+/* Resource categories */
+
+
+.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+.network-category-documents .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
+}
+
+.network-category-documents.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
+}
+
+.network-category-stylesheets .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
+}
+
+.network-category-stylesheets.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
+}
+
+.network-category-images .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
+}
+
+.network-category-images.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
+}
+
+.network-category-fonts .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
+}
+
+.network-category-fonts.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
+}
+
+.network-category-scripts .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
+}
+
+.network-category-scripts.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
+}
+
+.network-category-xhr .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
+}
+
+.network-category-xhr.resource-cached .network-graph-bar {
+    -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
+}
+
+.network-category-websockets .network-graph-bar {
+    -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.network-category-websockets.resource-cached .network-graph-bar {
+   -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+
+/* Popover */
+
+.network-timing-row {
+    position: relative;
+    height: 16px;
+}
+
+.network-timing-bar {
+    position: absolute;
+    background-color: red;
+    border-left: 1px solid red;
+    opacity: 0.4;
+    top: 0;
+    bottom: 0;
+}
+
+.network-timing-bar-title {
+    position: absolute;
+    color: black;
+    top: 1px;
+}
+
+.network-dim-cell {
+    color: grey;
+}
+
+/* Dividers */
+
+.network-timeline-grid {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    pointer-events: none;
+}
+
+.network-event-divider-padding {
+    position: absolute;
+    width: 8px;
+    top: 0;
+    bottom: 0;
+    pointer-events: auto;
+}
+
+.network-event-divider {
+    position: absolute;
+    width: 2px;
+    top: 31px;
+    bottom: 0;
+    z-index: 300;
+}
+
+.network-sidebar .network-timeline-grid.small .network-event-divider {
+    top: 23px;
+}
+
+.network-red-divider {
+    background-color: rgba(255, 0, 0, 0.5);
+}
+
+.network-blue-divider {
+    background-color: rgba(0, 0, 255, 0.5);
+}
+
+.network-sidebar .resources-dividers {
+    z-index: 0;
+}
+
+.network-sidebar .resources-dividers-label-bar {
+    background-color: transparent;
+    border: none;
+    height: 30px;
+    pointer-events: none;
+}
+
+.network-sidebar .network-timeline-grid.small .resources-dividers-label-bar {
+    height: 23px;
+}
+
+.network-sidebar .resources-divider-label {
+    top: 0px;
+    margin-top: -4px;
+    color: black;
+}
+
+.network-sidebar .resources-dividers-label-bar .resources-divider {
+    top: 23px;
+}
+
+.network-sidebar .network-timeline-grid.small .resources-dividers-label-bar .resources-divider {
+    top: 15px;
+}
+
+.network-sidebar .resources-divider.first .resources-divider-label {
+    display: none;
+}
+
+.network-sidebar .resources-dividers-label-bar .resources-divider.first {
+    background-color: transparent;
+}
+
+/* Filters */
+#network-filter {
+    margin-top: 1px;
+}
+
+.data-grid table.data tr.revealed.network-item {
+    display: none;
+}
+
+.data-grid.filter-all table.data tr.revealed.network-item,
+.data-grid.filter-documents table.data tr.revealed.network-category-documents,
+.data-grid.filter-stylesheets table.data tr.revealed.network-category-stylesheets,
+.data-grid.filter-images table.data tr.revealed.network-category-images,
+.data-grid.filter-scripts table.data tr.revealed.network-category-scripts,
+.data-grid.filter-xhr table.data tr.revealed.network-category-xhr,
+.data-grid.filter-fonts table.data tr.revealed.network-category-fonts,
+.data-grid.filter-websockets table.data tr.revealed.network-category-websockets,
+.data-grid.filter-other table.data tr.revealed.network-category-other {
+    display: table-row;
+}
+
+/* Summary */
+
+.network-summary-bar {
+    background-color: rgb(101, 111, 130);
+    color: white;
+    height: 20px;
+    font-size: 11px;
+    font-weight: bold;
+    padding-top: 3px;
+    padding-left: 10px;
+    z-index: 2000;
+    white-space: pre;
+    overflow : hidden;
+    text-overflow : ellipsis;
+}
+
+.network-summary-bar-bottom {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    padding-top: 3px;
+}
+
+.data-grid td .network-summary-bar {
+    white-space: pre;
+}
+
+.network-sidebar .data-grid td.network-summary {
+    padding: 0;
+}
+
+/* Viewer */
+
+.network.panel.viewing-resource .network-sidebar .data-grid td,
+.network.panel.viewing-resource .network-sidebar .data-grid th {
+    border-right: none;
+}
+
+.network.panel.viewing-resource .data-grid th.corner {
+    display: none;
+}
+
+#network-container {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    border-right: 0 none transparent;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.network.panel.viewing-resource #network-container {
+    border-right: 1px solid rgb(163, 163, 163);
+}
+
+#network-views {
+    position: absolute;
+    background: rgb(203, 203, 203);
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+}
+
+#network-close-button {
+    position: absolute;
+    width: 14px;
+    height: 14px;
+    background-image: url(Images/closeButtons.png);
+    background-position: 0 0;
+    background-color: transparent;
+    border: 0 none transparent;
+    top: 8px;
+    left: 5px;
+    z-index: 10;
+    display: none;
+}
+
+#network-views.small #network-close-button  {
+    top: 4px;
+}
+
+#network-close-button:hover {
+    background-position: 14px 0;
+}
+
+#network-close-button:active {
+    background-position: 28px 0;
+}
+
+.network.panel.viewing-resource #network-close-button  {
+    display: block;
+}
+
+
+.network-sidebar .data-grid.full-grid-mode .viewer-column {
+    display: none;
+}
+
+.network-sidebar .data-grid.brief-grid-mode .viewer-column,
+.network-sidebar .data-grid.brief-grid-mode .method-column,
+.network-sidebar .data-grid.brief-grid-mode .status-column,
+.network-sidebar .data-grid.brief-grid-mode .type-column,
+.network-sidebar .data-grid.brief-grid-mode .size-column,
+.network-sidebar .data-grid.brief-grid-mode .time-column {
+    display: none;
+}
+
+.network.panel.viewing-resource .network-timeline-grid {
+    display: none;
+}
+
+.network-sidebar .data-grid.viewing-resource-mode .method-column,
+.network-sidebar .data-grid.viewing-resource-mode .status-column,
+.network-sidebar .data-grid.viewing-resource-mode .type-column,
+.network-sidebar .data-grid.viewing-resource-mode .size-column,
+.network-sidebar .data-grid.viewing-resource-mode .time-column,
+.network-sidebar .data-grid.viewing-resource-mode .timeline-column {
+    display: none;
+}
+
+.network.panel .network-sidebar {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+
+.network.panel:not(.viewing-resource) .sidebar-resizer-vertical {
+    display: none;
+}
+
+.network.panel.viewing-resource .network-sidebar .data-grid-resizer {
+    display: none;
+}
+
+.network.panel .scope-bar {
+    height: 23px;
+    padding-top: 5px;
+}
+
+.network.panel:not(.viewing-resource) .data-grid tr.selected {
+    background-color: transparent;
+    color: black;
+}
+
+#network-views .network-item-view .tabbed-pane-header {
+    height: 31px;
+    padding-top: 8px;
+    padding-left: 25px;
+    white-space: nowrap;
+}
+
+#network-views.small .network-item-view .tabbed-pane-header {
+    height: 23px;
+    padding-top: 0;
+}
+
+.network.panel.viewing-resource .data-grid .data-container {
+    padding-right: 0;
+}
+
+.network-item-view {
+    display: none;
+    position: absolute;
+    background: white;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.network-item-view.visible {
+    display: -webkit-box;
+}
+
+.network-item-view .tabbed-pane-header {
+    height: 20px;
+    background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(236, 236, 236)), to(rgb(217, 217, 217)));
+    border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.network-item-view .scope-bar li {
+    border-bottom-left-radius: 0;
+    border-bottom-right-radius: 0;
+}
+
+.resource-headers-view {
+    display: none;
+    padding: 6px;
+    -webkit-user-select: text;    
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    overflow: auto;
+}
+
+.resource-headers-view.visible {
+    display: block;
+}
+
+.resource-headers-view .outline-disclosure .parent {
+    -webkit-user-select: none;
+    font-weight: bold;
+}
+
+.resource-headers-view .outline-disclosure .children li {
+    white-space: nowrap;
+}
+
+.resource-headers-view .outline-disclosure li.expanded .header-count {
+    display: none;
+}
+
+.resource-headers-view .outline-disclosure .header-name {
+    color: rgb(33%, 33%, 33%);
+    display: inline-block;
+    margin-right: 0.5em;
+    font-weight: bold;
+    vertical-align: top;
+    white-space: pre-wrap;
+}
+
+.resource-headers-view .outline-disclosure .header-value {
+    display: inline;
+    margin-right: 100px;
+    white-space: pre-wrap;
+    word-break: break-all;
+    margin-top: 1px;
+}
+
+.resource-headers-view .outline-disclosure .raw-form-data {
+    white-space: pre-wrap;
+}
+
+.resource-cookies-view {
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    overflow: auto;
+    padding: 12px;
+    height: 100%;
+}
+
+.resource-cookies-view.visible {
+    display: block;
+}
+
+.resource-cookies-view .data-grid {
+    height: 100%;
+}
+
+.resource-cookies-view .data-grid .row-group {
+    font-weight: bold;
+    font-size: 11px;
+}
+
+.resource-timing-view {
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    padding: 6px;
+    font-weight: bold;
+    font-size: 11px;
+    color: rgb(30%, 30%, 30%);
+}
+
+.resource-timing-view table {
+    border-spacing: 21px 0;
+}
+
+.resource-timing-view .network-timing-bar {
+    opacity: 1;
+}
+
+.resource-timing-view .network-timing-bar.proxy {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(239, 228, 176)), to(rgb(139, 128, 76)));
+    border-left: 1px solid rgb(139, 128, 76);
+}
+
+.resource-timing-view .network-timing-bar.dns {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(153, 208, 216)), to(rgb(81, 174, 189)));
+    border-left: 1px solid rgb(81, 174, 189);
+}
+
+.resource-timing-view .network-timing-bar.connecting {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(203, 232, 145)), to(rgb(160, 214, 56)));
+    border-left: 1px solid rgb(160, 214, 56);
+}
+
+.resource-timing-view .network-timing-bar.ssl {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(21, 232, 145)), to(rgb(216, 149, 132)));
+    border-left: 1px solid rgb(216, 149, 132);
+}
+
+.resource-timing-view .network-timing-bar.sending {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(232, 192, 182)), to(rgb(216, 147, 130)));
+    border-left: 1px solid rgb(216, 147, 130);
+}
+
+.resource-timing-view .network-timing-bar.waiting {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(188, 179, 208)), to(rgb(141, 125, 175)));
+    border-left: 1px solid rgb(141, 125, 175);
+}
+
+.resource-timing-view .network-timing-bar.receiving {
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(214, 214, 214)), to(rgb(182, 182, 182)));
+    border-left: 1px solid rgb(182, 182, 182);
+}
+
+.resource-timing-view.visible {
+    display: block;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/popover.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/popover.css
new file mode 100644
index 0000000..ae6f610
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/popover.css
@@ -0,0 +1,200 @@
+.popover {
+    position: absolute;
+    -webkit-border-image: url(Images/popoverBackground.png) 25 25 25 25;
+    border-width: 25px;
+    z-index: 100;
+    pointer-events: none;
+}
+
+.popover .content {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    pointer-events: auto;
+    overflow: auto;
+}
+
+.popover .arrow {
+    position: absolute;
+    background-image: url(Images/popoverArrows.png);
+    width: 19px;
+    height: 19px;
+    margin-left: 15px;
+    margin-top: -25px;
+    top: 0;
+    left: 0;
+}
+
+.popover.top-left-arrow .arrow {
+    /* The default is top-left, no styles needed. */
+}
+
+.popover.top-right-arrow .arrow {
+    right: 25px;
+    left: auto;
+}
+
+.popover.bottom-left-arrow .arrow {
+    top: auto;
+    bottom: 0;
+    margin-top: 0;
+    margin-bottom: -25px;
+    background-position: 0 -19px;
+}
+
+.popover.bottom-right-arrow .arrow {
+    right: 15px;
+    left: auto;
+    top: auto;
+    bottom: 0;
+    margin-top: 0;
+    margin-bottom: -25px;
+    background-position: 0 -19px;
+}
+
+.popover.left-top-arrow .arrow {
+    top: 0;
+    margin-top: 15px;
+    margin-left: -25px;
+    background-position: 0 -38px;
+}
+
+.popover.left-bottom-arrow .arrow {
+    top: auto;
+    bottom: 0;
+    margin-bottom: 15px;
+    margin-left: -25px;
+    background-position: 0 -38px;
+}
+
+.popover.right-top-arrow .arrow {
+    right: 0;
+    left: auto;
+    top: 0;
+    margin-top: 15px;
+    margin-right: -25px;
+    background-position: 0 -57px;
+}
+
+.popover.right-bottom-arrow .arrow {
+    right: 0;
+    left: auto;
+    top: auto;
+    bottom: 0;
+    margin-bottom: 15px;
+    margin-right: -25px;
+    background-position: 0 -57px;
+}
+
+.popover ::-webkit-scrollbar {
+    width: 11px;
+    height: 11px;
+}
+
+.popover ::-webkit-scrollbar-corner {
+    display: none;
+}
+
+.popover ::-webkit-resizer {
+    display: none;
+}
+
+/* Horizontal Scrollbar Styles */
+
+.popover ::-webkit-scrollbar:horizontal:corner-present {
+    border-right-width: 0;
+}
+
+.popover ::-webkit-scrollbar-thumb:horizontal {
+    -webkit-border-image: url(Images/thumbHoriz.png) 0 11 0 11;
+    border-color: transparent;
+    border-width: 0 11px;
+    min-width: 20px;
+}
+
+.popover ::-webkit-scrollbar-thumb:horizontal:hover {
+    -webkit-border-image: url(Images/thumbHoverHoriz.png) 0 11 0 11;
+}
+
+.popover ::-webkit-scrollbar-thumb:horizontal:active {
+    -webkit-border-image: url(Images/thumbActiveHoriz.png) 0 11 0 11;
+}
+
+.popover ::-webkit-scrollbar-track-piece:horizontal:start {
+    margin-left: 5px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:horizontal:end {
+    margin-right: 5px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:horizontal:end:corner-present {
+    margin-right: 4px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:horizontal:decrement {
+    -webkit-border-image: url(Images/trackHoriz.png) 0 11 0 11;
+    border-color: transparent;
+    border-width: 0 0 0 11px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:horizontal:increment {
+    -webkit-border-image: url(Images/trackHoriz.png) 0 11 0 11;
+    border-color: transparent;
+    border-width: 0 11px 0 0;
+}
+
+/* Vertical Scrollbar Styles */
+
+
+.popover ::-webkit-scrollbar:vertical:corner-present {
+    border-bottom-width: 0;
+}
+
+.popover ::-webkit-scrollbar-thumb:vertical {
+    -webkit-border-image: url(Images/thumbVert.png) 11 0 11 0;
+    border-color: transparent;
+    border-width: 11px 0;
+    min-height: 20px;
+}
+
+.popover ::-webkit-scrollbar-thumb:vertical:hover {
+    -webkit-border-image: url(Images/thumbHoverVert.png) 11 0 11 0;
+}
+
+.popover ::-webkit-scrollbar-thumb:vertical:active {
+    -webkit-border-image: url(Images/thumbActiveVert.png) 11 0 11 0;
+}
+
+
+.popover ::-webkit-scrollbar-track-piece:vertical:start {
+    margin-top: 5px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:vertical:end {
+    margin-bottom: 5px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:vertical:end:corner-present {
+    margin-bottom: 4px;
+}
+
+.popover ::-webkit-scrollbar-track-piece:vertical:decrement {
+    -webkit-border-image: url(Images/trackVert.png) 11 0 11 0;
+    border-color: transparent;
+    border-width: 11px 0 0 0;
+}
+
+.popover ::-webkit-scrollbar-track-piece:vertical:increment {
+    -webkit-border-image: url(Images/trackVert.png) 11 0 11 0;
+    border-color: transparent;
+    border-width: 0 0 11px 0;
+}
+
+/* Forced Scrollbar Mode Styles */
+
+.popover ::-webkit-scrollbar-button {
+    display: none;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/textViewer.css b/weinre.build/vendor/webkit/WebCore/inspector/front-end/textViewer.css
new file mode 100644
index 0000000..f6aa65e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/textViewer.css
@@ -0,0 +1,193 @@
+.text-editor {
+    position: absolute;
+    top:0;
+    left:0;
+    right:0;
+    bottom:0;
+    white-space: pre;
+    overflow: auto;
+}
+
+.text-editor-lines {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    overflow: hidden;
+    -webkit-user-select: none;
+}
+
+.text-editor-contents {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    overflow: auto;
+    -webkit-user-select: text;
+}
+
+.text-editor-editable {
+    -webkit-user-modify: read-write-plaintext-only;
+}
+
+.webkit-line-decorations {
+    pointer-events: none;
+    -webkit-user-select: none;
+    -webkit-user-modify: read-only;
+}
+
+.webkit-html-message-bubble {
+    -webkit-box-shadow: black 0px 2px 5px;
+    -webkit-border-radius: 9px;
+    -webkit-border-fit: lines;
+    font-size: 10px;
+    font-family: Lucida Grande, sans-serif;
+    font-weight: bold;
+    margin: 6px 25px;
+    padding: 0 7px 1px;
+    z-index:20;
+}
+
+.webkit-html-warning-message {
+    background-color: rgb(100%, 62%, 42%);
+    border: 2px solid rgb(100%, 52%, 21%);
+}
+
+.webkit-html-error-message {
+    background-color: rgb(100%, 42%, 42%);
+    border: 2px solid rgb(100%, 31%, 31%);
+}
+
+.webkit-html-message-line {
+    padding-left: 23px;
+    text-indent: -20px;
+}
+
+.webkit-html-message-line-hover {
+    padding-left: 23px;
+    text-indent: -20px;
+    white-space: auto;
+    text-overflow: auto;
+    overflow: auto;
+}
+
+.webkit-html-message-icon {
+    position: relative;
+    top: 2px;
+    margin: 0 4px;
+}
+
+.webkit-line-number {
+    color: rgb(128, 128, 128);
+    background-color: rgb(240, 240, 240);
+    border-right: 1px solid rgb(187, 187, 187);
+    text-align: right;
+    vertical-align: top;
+    word-break: normal;
+    padding-right: 4px;
+    padding-left: 6px;
+}
+
+.webkit-line-number-outer {
+    margin-right: -4px;
+    margin-left: -4px;
+    border-color: transparent;
+    border-style: solid;
+    border-width: 0 0 0px 2px;
+    vertical-align: top;
+}
+
+.webkit-line-number-inner {
+    margin-right: 4px;
+}
+
+.webkit-breakpoint .webkit-line-number-inner, .webkit-breakpoint-conditional .webkit-line-number-inner, .webkit-execution-line .webkit-line-number-inner {
+    margin-right: -10px;
+}
+
+.webkit-line-content {
+    padding-left: 2px;
+}
+
+.webkit-breakpoint .webkit-line-number-outer {
+    color: white;
+    border-width: 0 14px 0px 2px;
+    -webkit-border-image: url(Images/breakpointBorder.png) 0 14 0 2;
+}
+
+.webkit-breakpoint-conditional .webkit-line-number-outer {
+    color: white;
+    border-width: 0 14px 0px 2px;
+    -webkit-border-image: url(Images/breakpointConditionalBorder.png) 0 14 0 2;
+}
+
+.webkit-execution-line .webkit-line-number-outer {
+    color: transparent;
+    border-width: 0 14px 0px 2px;
+    -webkit-border-image: url(Images/programCounterBorder.png) 0 14 0 2;
+}
+
+.webkit-breakpoint.webkit-execution-line .webkit-line-number-outer {
+    color: white;
+    -webkit-border-image: url(Images/breakpointCounterBorder.png) 0 14 0 2;
+}
+
+.webkit-breakpoint.webkit-execution-line .webkit-line-number-outer {
+    color: transparent;
+    -webkit-border-image: url(Images/breakpointCounterBorder.png) 0 14 0 2;
+}
+
+.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number-outer {
+    color: transparent;
+    -webkit-border-image: url(Images/breakpointConditionalCounterBorder.png) 0 14 0 2;
+}
+
+.webkit-breakpoint-disabled .webkit-line-number-outer {
+    opacity: 0.5;
+}
+
+.breakpoints-deactivated .webkit-breakpoint .webkit-line-number-outer {
+    opacity: 0.5;
+}
+
+.breakpoints-deactivated .webkit-breakpoint-disabled .webkit-line-number-outer {
+    opacity: 0.3;
+}
+
+.webkit-execution-line.webkit-line-content {
+    background-color: rgb(171, 191, 254);
+    outline: 1px solid rgb(64, 115, 244);
+}
+
+.diff-container .webkit-added-line.webkit-line-content {
+    background-color: rgb(220, 255, 220);
+}
+
+.diff-container .webkit-removed-line.webkit-line-content {
+    background-color: rgb(255, 220, 220);
+    text-decoration: line-through;
+}
+
+.diff-container .webkit-changed-line.webkit-line-content {
+    background-color: rgb(220, 220, 255);
+}
+
+.webkit-search-result {
+    -webkit-border-radius: 4px;
+    padding: 2px 2px 2px 3px;
+    margin: -2px -2px -2px -3px;
+    opacity: 0.8;
+    -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px;
+    background-color: rgb(241, 234, 0);
+    color: black;
+}
+
+.webkit-highlighted-line.webkit-line-content {
+    -webkit-animation: "fadeout" 2s 0s;
+}
+
+@-webkit-keyframes fadeout {
+    from {background-color: rgb(255, 255, 120); }
+    to { background-color: white; }
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/treeoutline.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/treeoutline.js
new file mode 100644
index 0000000..27bc839
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/treeoutline.js
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function TreeOutline(listNode)
+{
+    this.children = [];
+    this.selectedTreeElement = null;
+    this._childrenListNode = listNode;
+    this._childrenListNode.removeChildren();
+    this._knownTreeElements = [];
+    this._treeElementsExpandedState = [];
+    this.expandTreeElementsWhenArrowing = false;
+    this.root = true;
+    this.hasChildren = false;
+    this.expanded = true;
+    this.selected = false;
+    this.treeOutline = this;
+
+    this._childrenListNode.tabIndex = 0;
+    this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true);
+}
+
+TreeOutline._knownTreeElementNextIdentifier = 1;
+
+TreeOutline._appendChild = function(child)
+{
+    if (!child)
+        throw("child can't be undefined or null");
+
+    var lastChild = this.children[this.children.length - 1];
+    if (lastChild) {
+        lastChild.nextSibling = child;
+        child.previousSibling = lastChild;
+    } else {
+        child.previousSibling = null;
+        child.nextSibling = null;
+    }
+
+    this.children.push(child);
+    this.hasChildren = true;
+    child.parent = this;
+    child.treeOutline = this.treeOutline;
+    child.treeOutline._rememberTreeElement(child);
+
+    var current = child.children[0];
+    while (current) {
+        current.treeOutline = this.treeOutline;
+        current.treeOutline._rememberTreeElement(current);
+        current = current.traverseNextTreeElement(false, child, true);
+    }
+
+    if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+        child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+    if (!this._childrenListNode) {
+        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+        this._childrenListNode.parentTreeElement = this;
+        this._childrenListNode.addStyleClass("children");
+        if (this.hidden)
+            this._childrenListNode.addStyleClass("hidden");
+    }
+
+    child._attach();
+}
+
+TreeOutline._insertChild = function(child, index)
+{
+    if (!child)
+        throw("child can't be undefined or null");
+
+    var previousChild = (index > 0 ? this.children[index - 1] : null);
+    if (previousChild) {
+        previousChild.nextSibling = child;
+        child.previousSibling = previousChild;
+    } else {
+        child.previousSibling = null;
+    }
+
+    var nextChild = this.children[index];
+    if (nextChild) {
+        nextChild.previousSibling = child;
+        child.nextSibling = nextChild;
+    } else {
+        child.nextSibling = null;
+    }
+
+    this.children.splice(index, 0, child);
+    this.hasChildren = true;
+    child.parent = this;
+    child.treeOutline = this.treeOutline;
+    child.treeOutline._rememberTreeElement(child);
+
+    var current = child.children[0];
+    while (current) {
+        current.treeOutline = this.treeOutline;
+        current.treeOutline._rememberTreeElement(current);
+        current = current.traverseNextTreeElement(false, child, true);
+    }
+
+    if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+        child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+    if (!this._childrenListNode) {
+        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+        this._childrenListNode.parentTreeElement = this;
+        this._childrenListNode.addStyleClass("children");
+        if (this.hidden)
+            this._childrenListNode.addStyleClass("hidden");
+    }
+
+    child._attach();
+}
+
+TreeOutline._removeChildAtIndex = function(childIndex)
+{
+    if (childIndex < 0 || childIndex >= this.children.length)
+        throw("childIndex out of range");
+
+    var child = this.children[childIndex];
+    this.children.splice(childIndex, 1);
+
+    var parent = child.parent;
+    if (child.deselect()) {
+        if (child.previousSibling)
+            child.previousSibling.select();
+        else if (child.nextSibling)
+            child.nextSibling.select();
+        else
+            parent.select();
+    }
+
+    if (child.previousSibling)
+        child.previousSibling.nextSibling = child.nextSibling;
+    if (child.nextSibling)
+        child.nextSibling.previousSibling = child.previousSibling;
+
+    if (child.treeOutline) {
+        child.treeOutline._forgetTreeElement(child);
+        child.treeOutline._forgetChildrenRecursive(child);
+    }
+
+    child._detach();
+    child.treeOutline = null;
+    child.parent = null;
+    child.nextSibling = null;
+    child.previousSibling = null;
+}
+
+TreeOutline._removeChild = function(child)
+{
+    if (!child)
+        throw("child can't be undefined or null");
+
+    var childIndex = this.children.indexOf(child);
+    if (childIndex === -1)
+        throw("child not found in this node's children");
+
+    TreeOutline._removeChildAtIndex.call(this, childIndex);
+}
+
+TreeOutline._removeChildren = function()
+{
+    for (var i = 0; i < this.children.length; ++i) {
+        var child = this.children[i];
+        child.deselect();
+
+        if (child.treeOutline) {
+            child.treeOutline._forgetTreeElement(child);
+            child.treeOutline._forgetChildrenRecursive(child);
+        }
+
+        child._detach();
+        child.treeOutline = null;
+        child.parent = null;
+        child.nextSibling = null;
+        child.previousSibling = null;
+    }
+
+    this.children = [];
+}
+
+TreeOutline._removeChildrenRecursive = function()
+{
+    var childrenToRemove = this.children;
+
+    var child = this.children[0];
+    while (child) {
+        if (child.children.length)
+            childrenToRemove = childrenToRemove.concat(child.children);
+        child = child.traverseNextTreeElement(false, this, true);
+    }
+
+    for (var i = 0; i < childrenToRemove.length; ++i) {
+        var child = childrenToRemove[i];
+        child.deselect();
+        if (child.treeOutline)
+            child.treeOutline._forgetTreeElement(child);
+        child._detach();
+        child.children = [];
+        child.treeOutline = null;
+        child.parent = null;
+        child.nextSibling = null;
+        child.previousSibling = null;
+    }
+
+    this.children = [];
+}
+
+TreeOutline.prototype._rememberTreeElement = function(element)
+{
+    if (!this._knownTreeElements[element.identifier])
+        this._knownTreeElements[element.identifier] = [];
+
+    // check if the element is already known
+    var elements = this._knownTreeElements[element.identifier];
+    if (elements.indexOf(element) !== -1)
+        return;
+
+    // add the element
+    elements.push(element);
+}
+
+TreeOutline.prototype._forgetTreeElement = function(element)
+{
+    if (this._knownTreeElements[element.identifier])
+        this._knownTreeElements[element.identifier].remove(element, true);
+}
+
+TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
+{
+    var child = parentElement.children[0];
+    while (child) {
+        this._forgetTreeElement(child);
+        child = child.traverseNextTreeElement(false, this, true);
+    }
+}
+
+TreeOutline.prototype.getCachedTreeElement = function(representedObject)
+{
+    if (!representedObject)
+        return null;
+
+    if ("__treeElementIdentifier" in representedObject) {
+        // If this representedObject has a tree element identifier, and it is a known TreeElement
+        // in our tree we can just return that tree element.
+        var elements = this._knownTreeElements[representedObject.__treeElementIdentifier];
+        if (elements) {
+            for (var i = 0; i < elements.length; ++i)
+                if (elements[i].representedObject === representedObject)
+                    return elements[i];
+        }
+    }
+    return null;
+}
+
+TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent)
+{
+    if (!representedObject)
+        return null;
+
+    var cachedElement = this.getCachedTreeElement(representedObject);
+    if (cachedElement)
+        return cachedElement;
+
+    // The representedObject isn't known, so we start at the top of the tree and work down to find the first
+    // tree element that represents representedObject or one of its ancestors.
+    var item;
+    var found = false;
+    for (var i = 0; i < this.children.length; ++i) {
+        item = this.children[i];
+        if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) {
+            found = true;
+            break;
+        }
+    }
+
+    if (!found)
+        return null;
+
+    // Make sure the item that we found is connected to the root of the tree.
+    // Build up a list of representedObject's ancestors that aren't already in our tree.
+    var ancestors = [];
+    var currentObject = representedObject;
+    while (currentObject) {
+        ancestors.unshift(currentObject);
+        if (currentObject === item.representedObject)
+            break;
+        currentObject = getParent(currentObject);
+    }
+
+    // For each of those ancestors we populate them to fill in the tree.
+    for (var i = 0; i < ancestors.length; ++i) {
+        // Make sure we don't call findTreeElement with the same representedObject
+        // again, to prevent infinite recursion.
+        if (ancestors[i] === representedObject)
+            continue;
+        // FIXME: we could do something faster than findTreeElement since we will know the next
+        // ancestor exists in the tree.
+        item = this.findTreeElement(ancestors[i], isAncestor, getParent);
+        if (item && item.onpopulate)
+            item.onpopulate(item);
+    }
+
+    return this.getCachedTreeElement(representedObject);
+}
+
+TreeOutline.prototype.treeElementFromPoint = function(x, y)
+{
+    var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
+    var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]);
+    if (listNode)
+        return listNode.parentTreeElement || listNode.treeElement;
+    return null;
+}
+
+TreeOutline.prototype._treeKeyDown = function(event)
+{
+    if (event.target !== this._childrenListNode)
+        return;
+
+    if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
+        return;
+
+    var handled = false;
+    var nextSelectedElement;
+    if (event.keyIdentifier === "Up" && !event.altKey) {
+        nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
+        while (nextSelectedElement && !nextSelectedElement.selectable)
+            nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
+        handled = nextSelectedElement ? true : false;
+    } else if (event.keyIdentifier === "Down" && !event.altKey) {
+        nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
+        while (nextSelectedElement && !nextSelectedElement.selectable)
+            nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
+        handled = nextSelectedElement ? true : false;
+    } else if (event.keyIdentifier === "Left") {
+        if (this.selectedTreeElement.expanded) {
+            if (event.altKey)
+                this.selectedTreeElement.collapseRecursively();
+            else
+                this.selectedTreeElement.collapse();
+            handled = true;
+        } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) {
+            handled = true;
+            if (this.selectedTreeElement.parent.selectable) {
+                nextSelectedElement = this.selectedTreeElement.parent;
+                handled = nextSelectedElement ? true : false;
+            } else if (this.selectedTreeElement.parent)
+                this.selectedTreeElement.parent.collapse();
+        }
+    } else if (event.keyIdentifier === "Right") {
+        if (!this.selectedTreeElement.revealed()) {
+            this.selectedTreeElement.reveal();
+            handled = true;
+        } else if (this.selectedTreeElement.hasChildren) {
+            handled = true;
+            if (this.selectedTreeElement.expanded) {
+                nextSelectedElement = this.selectedTreeElement.children[0];
+                handled = nextSelectedElement ? true : false;
+            } else {
+                if (event.altKey)
+                    this.selectedTreeElement.expandRecursively();
+                else
+                    this.selectedTreeElement.expand();
+            }
+        }
+    } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code || event.keyCode === WebInspector.KeyboardShortcut.Keys.Delete.code) {
+        if (this.selectedTreeElement.ondelete)
+            handled = this.selectedTreeElement.ondelete();
+    } else if (isEnterKey(event)) {
+        if (this.selectedTreeElement.onenter)
+            handled = this.selectedTreeElement.onenter();
+    }
+
+    if (nextSelectedElement) {
+        nextSelectedElement.reveal();
+        nextSelectedElement.select(false, true);
+    }
+
+    if (handled) {
+        event.preventDefault();
+        event.stopPropagation();
+    }
+}
+
+TreeOutline.prototype.expand = function()
+{
+    // this is the root, do nothing
+}
+
+TreeOutline.prototype.collapse = function()
+{
+    // this is the root, do nothing
+}
+
+TreeOutline.prototype.revealed = function()
+{
+    return true;
+}
+
+TreeOutline.prototype.reveal = function()
+{
+    // this is the root, do nothing
+}
+
+TreeOutline.prototype.select = function()
+{
+    // this is the root, do nothing
+}
+
+TreeOutline.prototype.appendChild = TreeOutline._appendChild;
+TreeOutline.prototype.insertChild = TreeOutline._insertChild;
+TreeOutline.prototype.removeChild = TreeOutline._removeChild;
+TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeOutline.prototype.removeChildren = TreeOutline._removeChildren;
+TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+function TreeElement(title, representedObject, hasChildren)
+{
+    this._title = title;
+    this.representedObject = (representedObject || {});
+
+    if (this.representedObject.__treeElementIdentifier)
+        this.identifier = this.representedObject.__treeElementIdentifier;
+    else {
+        this.identifier = TreeOutline._knownTreeElementNextIdentifier++;
+        this.representedObject.__treeElementIdentifier = this.identifier;
+    }
+
+    this._hidden = false;
+    this.expanded = false;
+    this.selected = false;
+    this.hasChildren = hasChildren;
+    this.children = [];
+    this.treeOutline = null;
+    this.parent = null;
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this._listItemNode = null;
+}
+
+TreeElement.prototype = {
+    selectable: true,
+    arrowToggleWidth: 10,
+
+    get listItemElement() {
+        return this._listItemNode;
+    },
+
+    get childrenListElement() {
+        return this._childrenListNode;
+    },
+
+    get title() {
+        return this._title;
+    },
+
+    set title(x) {
+        this._title = x;
+        this._setListItemNodeContent();
+    },
+
+    get titleHTML() {
+        return this._titleHTML;
+    },
+
+    set titleHTML(x) {
+        this._titleHTML = x;
+        this._setListItemNodeContent();
+    },
+
+    get tooltip() {
+        return this._tooltip;
+    },
+
+    set tooltip(x) {
+        this._tooltip = x;
+        if (this._listItemNode)
+            this._listItemNode.title = x ? x : "";
+    },
+
+    get hasChildren() {
+        return this._hasChildren;
+    },
+
+    set hasChildren(x) {
+        if (this._hasChildren === x)
+            return;
+
+        this._hasChildren = x;
+
+        if (!this._listItemNode)
+            return;
+
+        if (x)
+            this._listItemNode.addStyleClass("parent");
+        else {
+            this._listItemNode.removeStyleClass("parent");
+            this.collapse();
+        }
+    },
+
+    get hidden() {
+        return this._hidden;
+    },
+
+    set hidden(x) {
+        if (this._hidden === x)
+            return;
+
+        this._hidden = x;
+
+        if (x) {
+            if (this._listItemNode)
+                this._listItemNode.addStyleClass("hidden");
+            if (this._childrenListNode)
+                this._childrenListNode.addStyleClass("hidden");
+        } else {
+            if (this._listItemNode)
+                this._listItemNode.removeStyleClass("hidden");
+            if (this._childrenListNode)
+                this._childrenListNode.removeStyleClass("hidden");
+        }
+    },
+
+    get shouldRefreshChildren() {
+        return this._shouldRefreshChildren;
+    },
+
+    set shouldRefreshChildren(x) {
+        this._shouldRefreshChildren = x;
+        if (x && this.expanded)
+            this.expand();
+    },
+
+    _setListItemNodeContent: function()
+    {
+        if (!this._listItemNode)
+            return;
+
+        if (!this._titleHTML && !this._title)
+            this._listItemNode.removeChildren();
+        else if (typeof this._titleHTML === "string")
+            this._listItemNode.innerHTML = this._titleHTML;
+        else if (typeof this._title === "string")
+            this._listItemNode.textContent = this._title;
+        else {
+            this._listItemNode.removeChildren();
+            if (this._title.parentNode)
+                this._title.parentNode.removeChild(this._title);
+            this._listItemNode.appendChild(this._title);
+        }
+    }
+}
+
+TreeElement.prototype.appendChild = TreeOutline._appendChild;
+TreeElement.prototype.insertChild = TreeOutline._insertChild;
+TreeElement.prototype.removeChild = TreeOutline._removeChild;
+TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeElement.prototype.removeChildren = TreeOutline._removeChildren;
+TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+TreeElement.prototype._attach = function()
+{
+    if (!this._listItemNode || this.parent._shouldRefreshChildren) {
+        if (this._listItemNode && this._listItemNode.parentNode)
+            this._listItemNode.parentNode.removeChild(this._listItemNode);
+
+        this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
+        this._listItemNode.treeElement = this;
+        this._setListItemNodeContent();
+        this._listItemNode.title = this._tooltip ? this._tooltip : "";
+
+        if (this.hidden)
+            this._listItemNode.addStyleClass("hidden");
+        if (this.hasChildren)
+            this._listItemNode.addStyleClass("parent");
+        if (this.expanded)
+            this._listItemNode.addStyleClass("expanded");
+        if (this.selected)
+            this._listItemNode.addStyleClass("selected");
+
+        this._listItemNode.addEventListener("mousedown", TreeElement.treeElementMouseDown, false);
+        this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false);
+        this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false);
+
+        if (this.onattach)
+            this.onattach(this);
+    }
+
+    var nextSibling = null;
+    if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
+        nextSibling = this.nextSibling._listItemNode;
+    this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
+    if (this._childrenListNode)
+        this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+    if (this.selected)
+        this.select();
+    if (this.expanded)
+        this.expand();
+}
+
+TreeElement.prototype._detach = function()
+{
+    if (this._listItemNode && this._listItemNode.parentNode)
+        this._listItemNode.parentNode.removeChild(this._listItemNode);
+    if (this._childrenListNode && this._childrenListNode.parentNode)
+        this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+}
+
+TreeElement.treeElementMouseDown = function(event)
+{
+    var element = event.currentTarget;
+    if (!element || !element.treeElement || !element.treeElement.selectable)
+        return;
+
+    if (element.treeElement.isEventWithinDisclosureTriangle(event))
+        return;
+
+    element.treeElement.selectOnMouseDown(event);
+}
+
+TreeElement.treeElementToggled = function(event)
+{
+    var element = event.currentTarget;
+    if (!element || !element.treeElement)
+        return;
+
+    if (!element.treeElement.isEventWithinDisclosureTriangle(event))
+        return;
+
+    if (element.treeElement.expanded) {
+        if (event.altKey)
+            element.treeElement.collapseRecursively();
+        else
+            element.treeElement.collapse();
+    } else {
+        if (event.altKey)
+            element.treeElement.expandRecursively();
+        else
+            element.treeElement.expand();
+    }
+    event.stopPropagation();
+}
+
+TreeElement.treeElementDoubleClicked = function(event)
+{
+    var element = event.currentTarget;
+    if (!element || !element.treeElement)
+        return;
+
+    if (element.treeElement.ondblclick)
+        element.treeElement.ondblclick.call(element.treeElement, event);
+    else if (element.treeElement.hasChildren && !element.treeElement.expanded)
+        element.treeElement.expand();
+}
+
+TreeElement.prototype.collapse = function()
+{
+    if (this._listItemNode)
+        this._listItemNode.removeStyleClass("expanded");
+    if (this._childrenListNode)
+        this._childrenListNode.removeStyleClass("expanded");
+
+    this.expanded = false;
+    if (this.treeOutline)
+        this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+    if (this.oncollapse)
+        this.oncollapse(this);
+}
+
+TreeElement.prototype.collapseRecursively = function()
+{
+    var item = this;
+    while (item) {
+        if (item.expanded)
+            item.collapse();
+        item = item.traverseNextTreeElement(false, this, true);
+    }
+}
+
+TreeElement.prototype.expand = function()
+{
+    if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode))
+        return;
+
+    if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
+        if (this._childrenListNode && this._childrenListNode.parentNode)
+            this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+
+        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+        this._childrenListNode.parentTreeElement = this;
+        this._childrenListNode.addStyleClass("children");
+
+        if (this.hidden)
+            this._childrenListNode.addStyleClass("hidden");
+
+        if (this.onpopulate)
+            this.onpopulate(this);
+
+        for (var i = 0; i < this.children.length; ++i)
+            this.children[i]._attach();
+
+        delete this._shouldRefreshChildren;
+    }
+
+    if (this._listItemNode) {
+        this._listItemNode.addStyleClass("expanded");
+        if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode)
+            this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+    }
+
+    if (this._childrenListNode)
+        this._childrenListNode.addStyleClass("expanded");
+
+    this.expanded = true;
+    if (this.treeOutline)
+        this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+    if (this.onexpand)
+        this.onexpand(this);
+}
+
+TreeElement.prototype.expandRecursively = function(maxDepth)
+{
+    var item = this;
+    var info = {};
+    var depth = 0;
+
+    // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+    // in some case can be infinite, since JavaScript objects can hold circular references.
+    // So default to a recursion cap of 3 levels, since that gives fairly good results.
+    if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
+        maxDepth = 3;
+
+    while (item) {
+        if (depth < maxDepth)
+            item.expand();
+        item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
+        depth += info.depthChange;
+    }
+}
+
+TreeElement.prototype.hasAncestor = function(ancestor) {
+    if (!ancestor)
+        return false;
+
+    var currentNode = this.parent;
+    while (currentNode) {
+        if (ancestor === currentNode)
+            return true;
+        currentNode = currentNode.parent;
+    }
+
+    return false;
+}
+
+TreeElement.prototype.reveal = function()
+{
+    var currentAncestor = this.parent;
+    while (currentAncestor && !currentAncestor.root) {
+        if (!currentAncestor.expanded)
+            currentAncestor.expand();
+        currentAncestor = currentAncestor.parent;
+    }
+
+    if (this.onreveal)
+        this.onreveal(this);
+}
+
+TreeElement.prototype.revealed = function()
+{
+    var currentAncestor = this.parent;
+    while (currentAncestor && !currentAncestor.root) {
+        if (!currentAncestor.expanded)
+            return false;
+        currentAncestor = currentAncestor.parent;
+    }
+
+    return true;
+}
+
+TreeElement.prototype.selectOnMouseDown = function(event)
+{
+    this.select(false, true);
+}
+
+TreeElement.prototype.select = function(supressOnSelect, selectedByUser)
+{
+    if (!this.treeOutline || !this.selectable || this.selected)
+        return;
+
+    if (this.treeOutline.selectedTreeElement)
+        this.treeOutline.selectedTreeElement.deselect();
+
+    this.selected = true;
+    this.treeOutline._childrenListNode.focus();
+
+    // Focusing on another node may detach "this" from tree.
+    if (!this.treeOutline)
+        return;
+    this.treeOutline.selectedTreeElement = this;
+    if (this._listItemNode)
+        this._listItemNode.addStyleClass("selected");
+
+    if (this.onselect && !supressOnSelect)
+        this.onselect(this, selectedByUser);
+}
+
+TreeElement.prototype.deselect = function(supressOnDeselect)
+{
+    if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
+        return false;
+
+    this.selected = false;
+    this.treeOutline.selectedTreeElement = null;
+    if (this._listItemNode)
+        this._listItemNode.removeStyleClass("selected");
+
+    if (this.ondeselect && !supressOnDeselect)
+        this.ondeselect(this);
+    return true;
+}
+
+TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info)
+{
+    if (!dontPopulate && this.hasChildren && this.onpopulate)
+        this.onpopulate(this);
+
+    if (info)
+        info.depthChange = 0;
+
+    var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0];
+    if (element && (!skipHidden || (skipHidden && this.expanded))) {
+        if (info)
+            info.depthChange = 1;
+        return element;
+    }
+
+    if (this === stayWithin)
+        return null;
+
+    element = skipHidden ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
+    if (element)
+        return element;
+
+    element = this;
+    while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
+        if (info)
+            info.depthChange -= 1;
+        element = element.parent;
+    }
+
+    if (!element)
+        return null;
+
+    return (skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
+}
+
+TreeElement.prototype.traversePreviousTreeElement = function(skipHidden, dontPopulate)
+{
+    var element = skipHidden ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
+    if (!dontPopulate && element && element.hasChildren && element.onpopulate)
+        element.onpopulate(element);
+
+    while (element && (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
+        if (!dontPopulate && element.hasChildren && element.onpopulate)
+            element.onpopulate(element);
+        element = (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]);
+    }
+
+    if (element)
+        return element;
+
+    if (!this.parent || this.parent.root)
+        return null;
+
+    return this.parent;
+}
+
+TreeElement.prototype.isEventWithinDisclosureTriangle = function(event)
+{
+    var left = this._listItemNode.totalOffsetLeft;
+    return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
+}
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/utilities.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/utilities.js
new file mode 100644
index 0000000..64670e1
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/utilities.js
@@ -0,0 +1,1087 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contains diff method based on Javascript Diff Algorithm By John Resig
+ * http://ejohn.org/files/jsdiff.js (released under the MIT license).
+ */
+
+Function.prototype.bind = function(thisObject)
+{
+    var func = this;
+    var args = Array.prototype.slice.call(arguments, 1);
+    function bound()
+    {
+        return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0)));
+    }
+    bound.toString = function() {
+        return "bound: " + func;
+    };
+    return bound;
+}
+
+Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
+{
+    var startNode;
+    var startOffset = 0;
+    var endNode;
+    var endOffset = 0;
+
+    if (!stayWithinNode)
+        stayWithinNode = this;
+
+    if (!direction || direction === "backward" || direction === "both") {
+        var node = this;
+        while (node) {
+            if (node === stayWithinNode) {
+                if (!startNode)
+                    startNode = stayWithinNode;
+                break;
+            }
+
+            if (node.nodeType === Node.TEXT_NODE) {
+                var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
+                for (var i = start; i >= 0; --i) {
+                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+                        startNode = node;
+                        startOffset = i + 1;
+                        break;
+                    }
+                }
+            }
+
+            if (startNode)
+                break;
+
+            node = node.traversePreviousNode(stayWithinNode);
+        }
+
+        if (!startNode) {
+            startNode = stayWithinNode;
+            startOffset = 0;
+        }
+    } else {
+        startNode = this;
+        startOffset = offset;
+    }
+
+    if (!direction || direction === "forward" || direction === "both") {
+        node = this;
+        while (node) {
+            if (node === stayWithinNode) {
+                if (!endNode)
+                    endNode = stayWithinNode;
+                break;
+            }
+
+            if (node.nodeType === Node.TEXT_NODE) {
+                var start = (node === this ? offset : 0);
+                for (var i = start; i < node.nodeValue.length; ++i) {
+                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+                        endNode = node;
+                        endOffset = i;
+                        break;
+                    }
+                }
+            }
+
+            if (endNode)
+                break;
+
+            node = node.traverseNextNode(stayWithinNode);
+        }
+
+        if (!endNode) {
+            endNode = stayWithinNode;
+            endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
+        }
+    } else {
+        endNode = this;
+        endOffset = offset;
+    }
+
+    var result = this.ownerDocument.createRange();
+    result.setStart(startNode, startOffset);
+    result.setEnd(endNode, endOffset);
+
+    return result;
+}
+
+Node.prototype.traverseNextTextNode = function(stayWithin)
+{
+    var node = this.traverseNextNode(stayWithin);
+    if (!node)
+        return;
+
+    while (node && node.nodeType !== Node.TEXT_NODE)
+        node = node.traverseNextNode(stayWithin);
+
+    return node;
+}
+
+Node.prototype.rangeBoundaryForOffset = function(offset)
+{
+    var node = this.traverseNextTextNode(this);
+    while (node && offset > node.nodeValue.length) {
+        offset -= node.nodeValue.length;
+        node = node.traverseNextTextNode(this);
+    }
+    if (!node)
+        return { container: this, offset: 0 };
+    return { container: node, offset: offset };
+}
+
+Element.prototype.removeStyleClass = function(className) 
+{
+    // Test for the simple case first.
+    if (this.className === className) {
+        this.className = "";
+        return;
+    }
+
+    var index = this.className.indexOf(className);
+    if (index === -1)
+        return;
+
+    this.className = this.className.split(" ").filter(function(s) {
+        return s && s !== className;
+    }).join(" ");
+}
+
+Element.prototype.removeMatchingStyleClasses = function(classNameRegex)
+{
+    var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
+    if (regex.test(this.className))
+        this.className = this.className.replace(regex, " ");
+}
+
+Element.prototype.addStyleClass = function(className) 
+{
+    if (className && !this.hasStyleClass(className))
+        this.className += (this.className.length ? " " + className : className);
+}
+
+Element.prototype.hasStyleClass = function(className) 
+{
+    if (!className)
+        return false;
+    // Test for the simple case
+    if (this.className === className)
+        return true;
+
+    var index = this.className.indexOf(className);
+    if (index === -1)
+        return false;
+    var toTest = " " + this.className + " ";
+    return toTest.indexOf(" " + className + " ", index) !== -1;
+}
+
+Element.prototype.positionAt = function(x, y)
+{
+    this.style.left = x + "px";
+    this.style.top = y + "px";
+}
+
+Element.prototype.pruneEmptyTextNodes = function()
+{
+    var sibling = this.firstChild;
+    while (sibling) {
+        var nextSibling = sibling.nextSibling;
+        if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "")
+            this.removeChild(sibling);
+        sibling = nextSibling;
+    }
+}
+
+Element.prototype.isScrolledToBottom = function()
+{
+    // This code works only for 0-width border
+    return this.scrollTop + this.clientHeight === this.scrollHeight;
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
+{
+    for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
+        for (var i = 0; i < nameArray.length; ++i)
+            if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
+                return node;
+    return null;
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
+{
+    return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
+}
+
+Node.prototype.enclosingNodeOrSelfWithClass = function(className)
+{
+    for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
+        if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
+            return node;
+    return null;
+}
+
+Node.prototype.enclosingNodeWithClass = function(className)
+{
+    if (!this.parentNode)
+        return null;
+    return this.parentNode.enclosingNodeOrSelfWithClass(className);
+}
+
+Element.prototype.query = function(query) 
+{
+    return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+}
+
+Element.prototype.removeChildren = function()
+{
+    if (this.firstChild)
+        this.textContent = "";
+}
+
+Element.prototype.isInsertionCaretInside = function()
+{
+    var selection = window.getSelection();
+    if (!selection.rangeCount || !selection.isCollapsed)
+        return false;
+    var selectionRange = selection.getRangeAt(0);
+    return selectionRange.startContainer === this || selectionRange.startContainer.isDescendant(this);
+}
+
+Element.prototype.createChild = function(elementName, className)
+{
+    var element = document.createElement(elementName);
+    if (className)
+        element.className = className;
+    this.appendChild(element);
+    return element;
+}
+
+Element.prototype.__defineGetter__("totalOffsetLeft", function()
+{
+    var total = 0;
+    for (var element = this; element; element = element.offsetParent)
+        total += element.offsetLeft + (this !== element ? element.clientLeft : 0);
+    return total;
+});
+
+Element.prototype.__defineGetter__("totalOffsetTop", function()
+{
+    var total = 0;
+    for (var element = this; element; element = element.offsetParent)
+        total += element.offsetTop + (this !== element ? element.clientTop : 0);
+    return total;
+});
+
+Element.prototype.offsetRelativeToWindow = function(targetWindow)
+{
+    var elementOffset = {x: 0, y: 0};
+    var curElement = this;
+    var curWindow = this.ownerDocument.defaultView;
+    while (curWindow && curElement) {
+        elementOffset.x += curElement.totalOffsetLeft;
+        elementOffset.y += curElement.totalOffsetTop;
+        if (curWindow === targetWindow)
+            break;
+
+        curElement = curWindow.frameElement;
+        curWindow = curWindow.parent;
+    }
+
+    return elementOffset;
+}
+
+KeyboardEvent.prototype.__defineGetter__("data", function()
+{
+    // Emulate "data" attribute from DOM 3 TextInput event.
+    // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data
+    switch (this.type) {
+        case "keypress":
+            if (!this.ctrlKey && !this.metaKey)
+                return String.fromCharCode(this.charCode);
+            else
+                return "";
+        case "keydown":
+        case "keyup":
+            if (!this.ctrlKey && !this.metaKey && !this.altKey)
+                return String.fromCharCode(this.which);
+            else
+                return "";
+    }
+});
+
+Text.prototype.select = function(start, end)
+{
+    start = start || 0;
+    end = end || this.textContent.length;
+
+    if (start < 0)
+        start = end + start;
+
+    var selection = window.getSelection();
+    selection.removeAllRanges();
+    var range = document.createRange();
+    range.setStart(this, start);
+    range.setEnd(this, end);
+    selection.addRange(range);
+    return this;
+}
+
+Element.prototype.__defineGetter__("selectionLeftOffset", function() {
+    // Calculate selection offset relative to the current element.
+
+    var selection = window.getSelection();
+    if (!selection.containsNode(this, true))
+        return null;
+
+    var leftOffset = selection.anchorOffset;
+    var node = selection.anchorNode;
+
+    while (node !== this) {
+        while (node.previousSibling) {
+            node = node.previousSibling;
+            leftOffset += node.textContent.length;
+        }
+        node = node.parentNode;
+    }
+
+    return leftOffset;
+});
+
+Node.prototype.isWhitespace = isNodeWhitespace;
+Node.prototype.displayName = nodeDisplayName;
+Node.prototype.isAncestor = function(node)
+{
+    return isAncestorNode(this, node);
+};
+Node.prototype.isDescendant = isDescendantNode;
+Node.prototype.traverseNextNode = traverseNextNode;
+Node.prototype.traversePreviousNode = traversePreviousNode;
+Node.prototype.onlyTextChild = onlyTextChild;
+
+String.prototype.hasSubstring = function(string, caseInsensitive)
+{
+    if (!caseInsensitive)
+        return this.indexOf(string) !== -1;
+    return this.match(new RegExp(string.escapeForRegExp(), "i"));
+}
+
+String.prototype.findAll = function(string)
+{
+    var matches = [];
+    var i = this.indexOf(string);
+    while (i !== -1) {
+        matches.push(i);
+        i = this.indexOf(string, i + string.length);
+    }
+    return matches;
+}
+
+String.prototype.lineEndings = function()
+{
+    if (!this._lineEndings) {
+        this._lineEndings = this.findAll("\n");
+        this._lineEndings.push(this.length);
+    }
+    return this._lineEndings;
+}
+
+String.prototype.asParsedURL = function()
+{
+    // RegExp groups:
+    // 1 - scheme
+    // 2 - hostname
+    // 3 - ?port
+    // 4 - ?path
+    // 5 - ?fragment
+    var match = this.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
+    if (!match)
+        return null;
+    var result = {};
+    result.scheme = match[1].toLowerCase();
+    result.host = match[2];
+    result.port = match[3];
+    result.path = match[4] || "/";
+    result.fragment = match[5];
+    return result;
+}
+
+String.prototype.escapeCharacters = function(chars)
+{
+    var foundChar = false;
+    for (var i = 0; i < chars.length; ++i) {
+        if (this.indexOf(chars.charAt(i)) !== -1) {
+            foundChar = true;
+            break;
+        }
+    }
+
+    if (!foundChar)
+        return this;
+
+    var result = "";
+    for (var i = 0; i < this.length; ++i) {
+        if (chars.indexOf(this.charAt(i)) !== -1)
+            result += "\\";
+        result += this.charAt(i);
+    }
+
+    return result;
+}
+
+String.prototype.escapeForRegExp = function()
+{
+    return this.escapeCharacters("^[]{}()\\.$*+?|");
+}
+
+String.prototype.escapeHTML = function()
+{
+    return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
+}
+
+String.prototype.collapseWhitespace = function()
+{
+    return this.replace(/[\s\xA0]+/g, " ");
+}
+
+String.prototype.trimURL = function(baseURLDomain)
+{
+    var result = this.replace(/^(https|http|file):\/\//i, "");
+    if (baseURLDomain)
+        result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
+    return result;
+}
+
+function isNodeWhitespace()
+{
+    if (!this || this.nodeType !== Node.TEXT_NODE)
+        return false;
+    if (!this.nodeValue.length)
+        return true;
+    return this.nodeValue.match(/^[\s\xA0]+$/);
+}
+
+function nodeDisplayName()
+{
+    if (!this)
+        return "";
+
+    switch (this.nodeType) {
+        case Node.DOCUMENT_NODE:
+            return "Document";
+
+        case Node.ELEMENT_NODE:
+            var name = "<" + this.nodeName.toLowerCase();
+
+            if (this.hasAttributes()) {
+                var value = this.getAttribute("id");
+                if (value)
+                    name += " id=\"" + value + "\"";
+                value = this.getAttribute("class");
+                if (value)
+                    name += " class=\"" + value + "\"";
+                if (this.nodeName.toLowerCase() === "a") {
+                    value = this.getAttribute("name");
+                    if (value)
+                        name += " name=\"" + value + "\"";
+                    value = this.getAttribute("href");
+                    if (value)
+                        name += " href=\"" + value + "\"";
+                } else if (this.nodeName.toLowerCase() === "img") {
+                    value = this.getAttribute("src");
+                    if (value)
+                        name += " src=\"" + value + "\"";
+                } else if (this.nodeName.toLowerCase() === "iframe") {
+                    value = this.getAttribute("src");
+                    if (value)
+                        name += " src=\"" + value + "\"";
+                } else if (this.nodeName.toLowerCase() === "input") {
+                    value = this.getAttribute("name");
+                    if (value)
+                        name += " name=\"" + value + "\"";
+                    value = this.getAttribute("type");
+                    if (value)
+                        name += " type=\"" + value + "\"";
+                } else if (this.nodeName.toLowerCase() === "form") {
+                    value = this.getAttribute("action");
+                    if (value)
+                        name += " action=\"" + value + "\"";
+                }
+            }
+
+            return name + ">";
+
+        case Node.TEXT_NODE:
+            if (isNodeWhitespace.call(this))
+                return "(whitespace)";
+            return "\"" + this.nodeValue + "\"";
+
+        case Node.COMMENT_NODE:
+            return "<!--" + this.nodeValue + "-->";
+            
+        case Node.DOCUMENT_TYPE_NODE:
+            var docType = "<!DOCTYPE " + this.nodeName;
+            if (this.publicId) {
+                docType += " PUBLIC \"" + this.publicId + "\"";
+                if (this.systemId)
+                    docType += " \"" + this.systemId + "\"";
+            } else if (this.systemId)
+                docType += " SYSTEM \"" + this.systemId + "\"";
+            if (this.internalSubset)
+                docType += " [" + this.internalSubset + "]";
+            return docType + ">";
+    }
+
+    return this.nodeName.toLowerCase().collapseWhitespace();
+}
+
+function isAncestorNode(ancestor, node)
+{
+    if (!node || !ancestor)
+        return false;
+
+    var currentNode = node.parentNode;
+    while (currentNode) {
+        if (ancestor === currentNode)
+            return true;
+        currentNode = currentNode.parentNode;
+    }
+    return false;
+}
+
+function isDescendantNode(descendant)
+{
+    return isAncestorNode(descendant, this);
+}
+
+function traverseNextNode(stayWithin)
+{
+    if (!this)
+        return;
+
+    var node = this.firstChild;
+    if (node)
+        return node;
+
+    if (stayWithin && this === stayWithin)
+        return null;
+
+    node = this.nextSibling;
+    if (node)
+        return node;
+
+    node = this;
+    while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
+        node = node.parentNode;
+    if (!node)
+        return null;
+
+    return node.nextSibling;
+}
+
+function traversePreviousNode(stayWithin)
+{
+    if (!this)
+        return;
+    if (stayWithin && this === stayWithin)
+        return null;
+    var node = this.previousSibling;
+    while (node && node.lastChild)
+        node = node.lastChild;
+    if (node)
+        return node;
+    return this.parentNode;
+}
+
+function onlyTextChild()
+{
+    if (!this)
+        return null;
+
+    var firstChild = this.firstChild;
+    if (!firstChild || firstChild.nodeType !== Node.TEXT_NODE)
+        return null;
+
+    var sibling = firstChild.nextSibling;
+    return sibling ? null : firstChild;
+}
+
+function appropriateSelectorForNode(node, justSelector)
+{
+    if (!node)
+        return "";
+
+    var lowerCaseName = node.localName || node.nodeName.toLowerCase();
+
+    var id = node.getAttribute("id");
+    if (id) {
+        var selector = "#" + id;
+        return (justSelector ? selector : lowerCaseName + selector);
+    }
+
+    var className = node.getAttribute("class");
+    if (className) {
+        var selector = "." + className.replace(/\s+/, ".");
+        return (justSelector ? selector : lowerCaseName + selector);
+    }
+
+    if (lowerCaseName === "input" && node.getAttribute("type"))
+        return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]";
+
+    return lowerCaseName;
+}
+
+function getDocumentForNode(node)
+{
+    return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
+}
+
+function parentNode(node)
+{
+    return node.parentNode;
+}
+
+Number.millisToString = function(ms, higherResolution)
+{
+    return Number.secondsToString(ms / 1000, higherResolution);
+}
+
+Number.secondsToString = function(seconds, higherResolution)
+{
+    if (seconds === 0)
+        return "0";
+
+    var ms = seconds * 1000;
+    if (higherResolution && ms < 1000)
+        return WebInspector.UIString("%.3fms", ms);
+    else if (ms < 1000)
+        return WebInspector.UIString("%.0fms", ms);
+
+    if (seconds < 60)
+        return WebInspector.UIString("%.2fs", seconds);
+
+    var minutes = seconds / 60;
+    if (minutes < 60)
+        return WebInspector.UIString("%.1fmin", minutes);
+
+    var hours = minutes / 60;
+    if (hours < 24)
+        return WebInspector.UIString("%.1fhrs", hours);
+
+    var days = hours / 24;
+    return WebInspector.UIString("%.1f days", days);
+}
+
+Number.bytesToString = function(bytes, higherResolution)
+{
+    if (typeof higherResolution === "undefined")
+        higherResolution = true;
+
+    if (bytes < 1024)
+        return WebInspector.UIString("%.0fB", bytes);
+
+    var kilobytes = bytes / 1024;
+    if (higherResolution && kilobytes < 1024)
+        return WebInspector.UIString("%.2fKB", kilobytes);
+    else if (kilobytes < 1024)
+        return WebInspector.UIString("%.0fKB", kilobytes);
+
+    var megabytes = kilobytes / 1024;
+    if (higherResolution)
+        return WebInspector.UIString("%.2fMB", megabytes);
+    else
+        return WebInspector.UIString("%.0fMB", megabytes);
+}
+
+Number.constrain = function(num, min, max)
+{
+    if (num < min)
+        num = min;
+    else if (num > max)
+        num = max;
+    return num;
+}
+
+HTMLTextAreaElement.prototype.moveCursorToEnd = function()
+{
+    var length = this.value.length;
+    this.setSelectionRange(length, length);
+}
+
+Object.defineProperty(Array.prototype, "remove", { value: function(value, onlyFirst)
+{
+    if (onlyFirst) {
+        var index = this.indexOf(value);
+        if (index !== -1)
+            this.splice(index, 1);
+        return;
+    }
+
+    var length = this.length;
+    for (var i = 0; i < length; ++i) {
+        if (this[i] === value)
+            this.splice(i, 1);
+    }
+}});
+
+Object.defineProperty(Array.prototype, "keySet", { value: function()
+{
+    var keys = {};
+    for (var i = 0; i < this.length; ++i)
+        keys[this[i]] = true;
+    return keys;
+}});
+
+Object.defineProperty(Array.prototype, "upperBound", { value: function(value)
+{
+    var first = 0;
+    var count = this.length;
+    while (count > 0) {
+      var step = count >> 1;
+      var middle = first + step;
+      if (value >= this[middle]) {
+          first = middle + 1;
+          count -= step + 1;
+      } else
+          count = step;
+    }
+    return first;
+}});
+
+Array.diff = function(left, right)
+{
+    var o = left;
+    var n = right;
+
+    var ns = {};
+    var os = {};
+
+    for (var i = 0; i < n.length; i++) {
+        if (ns[n[i]] == null)
+            ns[n[i]] = { rows: [], o: null };
+        ns[n[i]].rows.push(i);
+    }
+
+    for (var i = 0; i < o.length; i++) {
+        if (os[o[i]] == null)
+            os[o[i]] = { rows: [], n: null };
+        os[o[i]].rows.push(i);
+    }
+
+    for (var i in ns) {
+        if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
+            n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] };
+            o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] };
+        }
+    }
+
+    for (var i = 0; i < n.length - 1; i++) {
+        if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {
+            n[i + 1] = { text: n[i + 1], row: n[i].row + 1 };
+            o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 };
+        }
+    }
+
+    for (var i = n.length - 1; i > 0; i--) {
+        if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && 
+            n[i - 1] == o[n[i].row - 1]) {
+            n[i - 1] = { text: n[i - 1], row: n[i].row - 1 };
+            o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 };
+        }
+    }
+
+    return { left: o, right: n };
+}
+
+Array.convert = function(list)
+{
+    // Cast array-like object to an array.
+    return Array.prototype.slice.call(list);
+}
+
+function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
+{
+    var first = 0;
+    var last = aList.length - 1;
+    var floor = Math.floor;
+    var mid, c;
+
+    while (first <= last) {
+        mid = floor((first + last) / 2);
+        c = aFunction(anObject, aList[mid]);
+
+        if (c > 0)
+            first = mid + 1;
+        else if (c < 0)
+            last = mid - 1;
+        else {
+            // Return the first occurance of an item in the list.
+            while (mid > 0 && aFunction(anObject, aList[mid - 1]) === 0)
+                mid--;
+            first = mid;
+            break;
+        }
+    }
+
+    return first;
+}
+
+String.sprintf = function(format)
+{
+    return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
+}
+
+String.tokenizeFormatString = function(format)
+{
+    var tokens = [];
+    var substitutionIndex = 0;
+
+    function addStringToken(str)
+    {
+        tokens.push({ type: "string", value: str });
+    }
+
+    function addSpecifierToken(specifier, precision, substitutionIndex)
+    {
+        tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
+    }
+
+    var index = 0;
+    for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
+        addStringToken(format.substring(index, precentIndex));
+        index = precentIndex + 1;
+
+        if (format[index] === "%") {
+            addStringToken("%");
+            ++index;
+            continue;
+        }
+
+        if (!isNaN(format[index])) {
+            // The first character is a number, it might be a substitution index.
+            var number = parseInt(format.substring(index));
+            while (!isNaN(format[index]))
+                ++index;
+            // If the number is greater than zero and ends with a "$",
+            // then this is a substitution index.
+            if (number > 0 && format[index] === "$") {
+                substitutionIndex = (number - 1);
+                ++index;
+            }
+        }
+
+        var precision = -1;
+        if (format[index] === ".") {
+            // This is a precision specifier. If no digit follows the ".",
+            // then the precision should be zero.
+            ++index;
+            precision = parseInt(format.substring(index));
+            if (isNaN(precision))
+                precision = 0;
+            while (!isNaN(format[index]))
+                ++index;
+        }
+
+        addSpecifierToken(format[index], precision, substitutionIndex);
+
+        ++substitutionIndex;
+        ++index;
+    }
+
+    addStringToken(format.substring(index));
+
+    return tokens;
+}
+
+String.standardFormatters = {
+    d: function(substitution)
+    {
+        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
+            substitution = substitution.description;
+        substitution = parseInt(substitution);
+        return !isNaN(substitution) ? substitution : 0;
+    },
+
+    f: function(substitution, token)
+    {
+        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
+            substitution = substitution.description;
+        substitution = parseFloat(substitution);
+        if (substitution && token.precision > -1)
+            substitution = substitution.toFixed(token.precision);
+        return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
+    },
+
+    s: function(substitution)
+    {
+        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) !== "null")
+            substitution = substitution.description;
+        return substitution;
+    },
+};
+
+String.vsprintf = function(format, substitutions)
+{
+    return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
+}
+
+String.format = function(format, substitutions, formatters, initialValue, append)
+{
+    if (!format || !substitutions || !substitutions.length)
+        return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
+
+    function prettyFunctionName()
+    {
+        return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
+    }
+
+    function warn(msg)
+    {
+        console.warn(prettyFunctionName() + ": " + msg);
+    }
+
+    function error(msg)
+    {
+        console.error(prettyFunctionName() + ": " + msg);
+    }
+
+    var result = initialValue;
+    var tokens = String.tokenizeFormatString(format);
+    var usedSubstitutionIndexes = {};
+
+    for (var i = 0; i < tokens.length; ++i) {
+        var token = tokens[i];
+
+        if (token.type === "string") {
+            result = append(result, token.value);
+            continue;
+        }
+
+        if (token.type !== "specifier") {
+            error("Unknown token type \"" + token.type + "\" found.");
+            continue;
+        }
+
+        if (token.substitutionIndex >= substitutions.length) {
+            // If there are not enough substitutions for the current substitutionIndex
+            // just output the format specifier literally and move on.
+            error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
+            result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
+            continue;
+        }
+
+        usedSubstitutionIndexes[token.substitutionIndex] = true;
+
+        if (!(token.specifier in formatters)) {
+            // Encountered an unsupported format character, treat as a string.
+            warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
+            result = append(result, substitutions[token.substitutionIndex]);
+            continue;
+        }
+
+        result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
+    }
+
+    var unusedSubstitutions = [];
+    for (var i = 0; i < substitutions.length; ++i) {
+        if (i in usedSubstitutionIndexes)
+            continue;
+        unusedSubstitutions.push(substitutions[i]);
+    }
+
+    return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
+}
+
+function isEnterKey(event) {
+    // Check if in IME.
+    return event.keyCode !== 229 && event.keyIdentifier === "Enter";
+}
+
+
+function highlightSearchResult(element, offset, length)
+{
+    var lineText = element.textContent;
+    var endOffset = offset + length;
+    var highlightNode = document.createElement("span");
+    highlightNode.className = "webkit-search-result";
+    highlightNode.textContent = lineText.substring(offset, endOffset);
+
+    var boundary = element.rangeBoundaryForOffset(offset);
+    var textNode = boundary.container;
+    var text = textNode.textContent;
+
+    if (boundary.offset + length < text.length) {
+        // Selection belong to a single split mode.
+        textNode.textContent = text.substring(boundary.offset + length);
+        textNode.parentElement.insertBefore(highlightNode, textNode);
+        var prefixNode = document.createTextNode(text.substring(0, boundary.offset));
+        textNode.parentElement.insertBefore(prefixNode, highlightNode);
+        return highlightNode;
+    }
+
+    var parentElement = textNode.parentElement;
+    var anchorElement = textNode.nextSibling;
+
+    length -= text.length - boundary.offset;
+    textNode.textContent = text.substring(0, boundary.offset);
+    textNode = textNode.traverseNextTextNode(element);
+
+    while (textNode) {
+        var text = textNode.textContent;
+        if (length < text.length) {
+            textNode.textContent = text.substring(length);
+            break;
+        }
+
+        length -= text.length;
+        textNode.textContent = "";
+        textNode = textNode.traverseNextTextNode(element);
+    }
+
+    parentElement.insertBefore(highlightNode, anchorElement);
+    return highlightNode;
+}
+
+function createSearchRegex(query)
+{
+    var regex = "";
+    for (var i = 0; i < query.length; ++i) {
+        var char = query.charAt(i);
+        if (char === "]")
+            char = "\\]";
+        regex += "[" + char + "]";
+    }
+    return new RegExp(regex, "i");
+}
+
+function offerFileForDownload(contents)
+{
+    var builder = new BlobBuilder();
+    builder.append(contents);
+    var blob = builder.getBlob("application/octet-stream");
+    var url = window.webkitURL.createObjectURL(blob);
+    window.open(url);
+}
diff --git a/weinre.build/weinre build.xml.launch b/weinre.build/weinre build.xml.launch
deleted file mode 100644
index 1f60c71..0000000
--- a/weinre.build/weinre build.xml.launch
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.ant.AntLaunchConfigurationType">
-<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="true"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6.0 (MacOS X Default)"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.ant.internal.launching.remote.InternalAntRunner"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="weinre.build"/>
-<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/weinre.build/build.xml}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/weinre.build}"/>
-<stringAttribute key="process_factory_id" value="org.eclipse.ant.ui.remoteAntProcessFactory"/>
-</launchConfiguration>
diff --git a/weinre.doc/.classpath b/weinre.doc/.classpath
deleted file mode 100644
index 8778ddd..0000000
--- a/weinre.doc/.classpath
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/weinre.doc/.project b/weinre.doc/.project
deleted file mode 100644
index 2858af2..0000000
--- a/weinre.doc/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>weinre.doc</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/weinre.doc/Building.body.html b/weinre.doc/Building.body.html
index f5dc33b..2425714 100644
--- a/weinre.doc/Building.body.html
+++ b/weinre.doc/Building.body.html
@@ -18,9 +18,9 @@
 -->
 
 <p>The source repository for weinre is maintained at
-<a href="https://github.com/callback/callback-weinre">GitHub</a>.
+<a href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git">Apache</a>.
 
-<p>At development time, <span class="weinre">weinre</span> consists of 5
-directories / Eclipse projects.  See the file <tt>README.md</tt> in the
-<tt>weinre.build</tt> directory for more instructions on
+<p>See the file 
+<tt><a href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=blob;f=README.md;hb=HEAD">README.md<a/></tt> 
+in the top-most directory of the source distribution for more instructions on
 how to perform a build.
diff --git a/weinre.doc/ChangeLog.body.html b/weinre.doc/ChangeLog.body.html
index 9759636..37bca7c 100644
--- a/weinre.doc/ChangeLog.body.html
+++ b/weinre.doc/ChangeLog.body.html
@@ -23,6 +23,16 @@
 <p><a href="https://github.com/callback/callback-weinre/downloads">https://github.com/callback/callback-weinre/downloads</a>
 
 <!-- ======================================================================= -->
+<h2>2012/??/?? - version 1.7.0</h2>
+
+<ul>
+
+<li><p>port the server from Java to node.js
+
+</ul>
+
+
+<!-- ======================================================================= -->
 <h2>2011/12/01 - version 1.6.1</h2>
 
 <ul>
diff --git a/weinre.doc/Home.body.html b/weinre.doc/Home.body.html
index 281414a..fd0638a 100644
--- a/weinre.doc/Home.body.html
+++ b/weinre.doc/Home.body.html
@@ -32,8 +32,8 @@
 <p>Interesting places to visit:
 <table>
 <tr><td>- videos at YouTube:               <td><a href="http://www.youtube.com/results?search_query=weinre">http://www.youtube.com/results?search_query=weinre</a>
-<tr><td>- this documentation at GitHub:    <td><a href="http://callback.github.com/callback-weinre">http://callback.github.com/callback-weinre</a>
-<tr><td>- source at GitHub:                <td><a href="https://github.com/callback/callback-weinre">https://github.com/callback/callback-weinre</a>
+<tr><td>- this documentation at Apache:    <td>[TBD]</a>
+<tr><td>- source at GitHub:                <td><a href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=summary">https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=summary</a>
 <tr><td>- discussion at Google Group:      <td><a href="http://groups.google.com/group/weinre">http://groups.google.com/group/weinre</a>
 </table>
 
@@ -139,11 +139,13 @@
 version of Prototype.js.
 </ul>
 
+<h3>Platforms supported - debug server</h3>
+<p>Any platform that supports <a href="http://nodejs.org/">node.js</a>.
+
 <h3>Platforms supported - debug client</h3>
 <p>The browser where the debugger user interface runs.
 
 <ul>
-<li>weinre Mac application - Mac OS X 10.6 64-bit
 <li>Google Chrome 8.x
 <li>Apple Safari 5.x
 </ul>
diff --git a/weinre.doc/Installing.body.html b/weinre.doc/Installing.body.html
index c64088a..c4854fc 100644
--- a/weinre.doc/Installing.body.html
+++ b/weinre.doc/Installing.body.html
@@ -17,20 +17,14 @@
  * under the License.
 -->
 
-<p><span class="weinre">weinre</span> is shipped as two archives
+<p><span class="weinre">weinre</span> is shipped as an archive
 available at
-<a href="https://github.com/callback/callback-weinre/archives/master">https://github.com/callback/callback-weinre/archives/master</a>
+<a href="">[TBD]</a>
 
 <ul class="spaced">
 
-<li><b><tt>weinre-jar-x.y.z.zip</tt></b>
-<br>This archive includes a Java .jar file.
-
-<li><b><tt>weinre-mac-x.y.z.zip</tt></b>
-<br>This archive includes a Mac OS X application.
+<li><b><tt>weinre-node-x.y.z.zip</tt></b>
 
 </ul>
 
-<p>Install the .jar and/or Mac OS X application wherever you wish.
-At runtime, the .jar file is not sensive to the directory
-it is installed in, or the current directory when it's launched.
+<p>Unzip the archive wherever you wish.
diff --git a/weinre.doc/License.body.html b/weinre.doc/License.body.html
index d775ca5..d42235b 100644
--- a/weinre.doc/License.body.html
+++ b/weinre.doc/License.body.html
@@ -17,35 +17,10 @@
  * under the License.
 -->
 
-<p>weinre contains code from the following other projects:
+<p>Source specific to weinre is all licensed under the 
+<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
 
-<ul class="spaced">
-
-<li>Files from <a href="http://webkit.org/">WebKit</a>.
-Web Inspector code.  Although WebKit in general contains both BSD and
-LGPL code, only BSD licensed code is used by weinre.
-
-<li>Files from <a href="http://www.eclipse.org/jetty/">Eclipse Jetty</a>.
-HTTP server.  License: ASLv2 and EPLv1
-
-<li>Files from <a href="http://www.eclipse.org/swt/">Eclipse SWT</a>.
-Platform UI toolkit.  License: EPLv1
-
-<li>Files from <a href="https://github.com/pmuellr/modjewel">modjewel</a>.
-CommonJS runtime for the browser.  License: MIT
-
-<li>Files from <a href="http://commons.apache.org/cli/">Apache Commons CLI</a>.
-Command-line parser.  License: ASLv2
-
-<li>Files from <a href="http://incubator.apache.org/wink/">Apache Wink</a>.
-JSON codecs.  License: ASLv2
-
-</ul>
-
-<p>The source for weinre itself is available under either
-the terms of the Apacle License, Version 2.0.  You may obtain a copy of the
-License at
-
-<blockquote>
-    <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
-</blockquote>
+<p>weinre also makes use of third party code; the licensing details for
+those is available in the 
+<a href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=blob;f=LICENSE;hb=HEAD">LICENSE</a>
+file in the top-most directory of the source distribution.
diff --git a/weinre.doc/MultiUser.body.html b/weinre.doc/MultiUser.body.html
index 177f363..599f000 100644
--- a/weinre.doc/MultiUser.body.html
+++ b/weinre.doc/MultiUser.body.html
@@ -104,6 +104,4 @@
 of weinre, each connected client and target have their channel and id's listed,
 if you can't remember what id you used with the client.
 
-<li>The client with the Mac application currently only supports the <code>anonymous</code> id.
-
 </ul>
\ No newline at end of file
diff --git a/weinre.doc/Running.body.html b/weinre.doc/Running.body.html
index 652bddd..6c2f228 100644
--- a/weinre.doc/Running.body.html
+++ b/weinre.doc/Running.body.html
@@ -31,8 +31,8 @@
 <dl class="spaced">
 
 <dt>Debug Server
-<dd>This is the HTTP server that you run from the <tt>weinre.jar</tt> file
-or the Mac application.  It's the HTTP server that's used by the
+<dd>This is the HTTP server that you run from the <tt>weinre-node</tt> distribution.
+It's the HTTP server that's used by the
 <b>Debug Client</b> and <b>Debug Target</b>.
 
 <dt>Debug Client
@@ -56,42 +56,19 @@
 <p>Typically, you run both the <b>Debug Client</b> and the <b>Debug Server</b>
 on your desktop/laptop, and the <b>Debug Target</b> on your mobile device.
 
-<p>When using the Mac application, the
-<b>Debug Client</b> and <b>Debug Server</b> are running
-in the same process.
-When you launch the application,
-the server starts, and then the browser included in the
-application is launched
-on the appropriate URL automagically.
-
-<p>When using the <tt>weinre.jar</tt> program instead
-of the Mac application, only the <b>Debug Server</b>
-is started.  You will need to launch the <b>Debug Client</b>
-in a web browser.
-
 <p>The <b>Debug Target</b> is the squirrelliest bit.  You
 will need to arrange to inject some JavaScript code, provided
 by the <b>Debug Server</b>, into your web page, in order for it
 to function as a <b>Debug Target</b>.
 
 <!-- ======================================================== -->
-<h2>Starting the debug server</h2>
+<h2>Running the debug server using the weinre-node distribution</h2>
 
-<p>There are two ways to run the <span class="weinre">weinre</span> debug server:
-
-<ul>
-<li>Running the debug server using the weinre.jar file
-<li>Running the debug server using the Mac application
-</ul>
-
-<!-- ======================================================== -->
-<h2>Running the debug server using the weinre.jar file</h2>
-
-<p>To run <span class="weinre">weinre</span> from the jar file,
+<p>To run <span class="weinre">weinre</span> from the weinre-node distribution,
 execute the following command:
 
 <pre>
-java -jar path/to/weinre.jar [options]
+node path-to-weinre-node/weinre [options]
 </pre>
 
 <p>Options available are:
@@ -130,12 +107,10 @@
 <p>Default: <tt>false</tt>
 </div>
 
-<li><tt>--reuseAddr [true | false]</tt>
+<li><tt>--debug [true | false]</tt>
 <div class="indent">
-<p>Sets the "reuseAddr" flag for Jetty.
+<p>Causes even more jibberish to be written to stdout
 <p>Default: <tt>false</tt>
-
-<p>May be needed if you restart your server frequently.
 </div>
 
 <li><tt>--readTimeout [seconds]</tt>
@@ -189,30 +164,6 @@
 
 <p>The server will run until you kill it.  Control-C will do the job.
 
-<p>Below is what you should see from the console after running
-<span class="weinre">weinre</span> from the <tt>weinre.jar</tt> file.
-
-<p><img src="images/shell.png">
-
-<!-- ======================================================== -->
-<h2>Running the debug server using the Mac application</h2>
-
-<p>Go back and read the description above about the weinre.jar settings.
-
-<p>Only the <tt>~/.weinre/server.properties</tt>
-file is available to configure the server, as there is no
-traditional command line used to launch Mac "applications".
-
-<p>The server will run until you quit the application.
-
-<p>Since there is no practical way to see the stdout and stdin
-from the server when running a Mac application, these streams
-are intercepted and displayed in the <b>Server Console</b>
-tab in the Mac application.
-
-<p>The Mac application also displays the server's home page
-in a separate tab.
-
 <!-- ======================================================== -->
 <h2>Running the debug server bound to something other than <tt>localhost</tt></h3>
 
diff --git a/weinre.doc/Security.body.html b/weinre.doc/Security.body.html
index d8c09e6..ab73f49 100644
--- a/weinre.doc/Security.body.html
+++ b/weinre.doc/Security.body.html
@@ -30,7 +30,7 @@
 <p>The primary security exposure with <span class="weinre">weinre</span> is via
 the debug server.
 
-<p>Currently, the server only reads files from the <tt>weinre.jar</tt> file,
+<p>Currently, the server only reads files from the weinre-node distribution,
 and from the <tt>~/.weinre/</tt> directory (for property files).
 The only thing the server writes to is <tt>stdout</tt> and <tt>stderr</tt>.
 
diff --git a/weinre.doc/TestDrive.body.html b/weinre.doc/TestDrive.body.html
index 1bd1c2d..7a71a65 100644
--- a/weinre.doc/TestDrive.body.html
+++ b/weinre.doc/TestDrive.body.html
@@ -52,11 +52,11 @@
 is the safe one, and good enough to run this walk through.
 
 <p>To start the server,
-<a href="Installing.html">install the <tt>weinre.jar</tt> file</a>,
+<a href="Installing.html">install the <tt>weinre.node</tt> server</a>,
 then run the following command:
 
 <pre>
-java -jar weinre.jar -httpPort 8081
+weinre -httpPort 8081
 </pre>
 
 <p><img src="images/weinre-con-01-h.jpg">
diff --git a/weinre.doc/boilerplate-header.html.txt b/weinre.doc/boilerplate-header.html.txt
index 77ae9ed..8e4039a 100644
--- a/weinre.doc/boilerplate-header.html.txt
+++ b/weinre.doc/boilerplate-header.html.txt
@@ -28,7 +28,7 @@
 
 <body>
 
-<a class="no-decoration" href="https://github.com/callback/callback-weinre"><div class="ribbon">Fork weinre on GitHub</div></a>
+<a class="no-decoration" href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git"><div class="ribbon">clone weinre at apache</div></a>
 
 <!-- ======================================================================= -->
 <h1 class="page-title">weinre - @PAGE_NAME@</h1>
diff --git a/weinre.server/.classpath b/weinre.server/.classpath
deleted file mode 100644
index 349aa08..0000000
--- a/weinre.server/.classpath
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/weinre.build"/>
-	<classpathentry exported="true" kind="lib" path="/weinre.build/vendor/cli/commons-cli.jar" sourcepath="/weinre.build/vendor/cli/commons-cli-src.jar"/>
-	<classpathentry exported="true" kind="lib" path="/weinre.build/vendor/jetty/jetty.jar" sourcepath="/weinre.build/vendor/jetty/jetty-src.jar"/>
-	<classpathentry exported="true" kind="lib" path="/weinre.build/vendor/json4j/json4j.jar" sourcepath="/weinre.build/vendor/json4j/json4j-src.jar"/>
-	<classpathentry exported="true" kind="lib" path="/weinre.build/vendor/jetty/servlet-api.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/weinre.server/.gitignore b/weinre.server/.gitignore
index ba077a4..9c2a02a 100644
--- a/weinre.server/.gitignore
+++ b/weinre.server/.gitignore
@@ -1 +1,4 @@
-bin
+tmp
+web
+build-info.txt
+package.json
\ No newline at end of file
diff --git a/weinre.server/.npmignore b/weinre.server/.npmignore
new file mode 100644
index 0000000..38afd85
--- /dev/null
+++ b/weinre.server/.npmignore
@@ -0,0 +1,4 @@
+.DS_Store
+.git*
+Makefile
+test/
\ No newline at end of file
diff --git a/weinre.server/.project b/weinre.server/.project
deleted file mode 100644
index ba22530..0000000
--- a/weinre.server/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>weinre.server</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/weinre.server/README.md b/weinre.server/README.md
new file mode 100644
index 0000000..fc2f570
--- /dev/null
+++ b/weinre.server/README.md
@@ -0,0 +1,47 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+-->
+
+The files contained in this directory are the source for the
+weinre server, implemented using the 
+[express package](http://expressjs.com/)
+on the 
+[node.js](http://nodejs.org) 
+runtime.
+
+The weinre server uses numerous 3rd party libraries, installed in the
+`node_modules` directory, and stored in the SCM.  
+In case these need to be updated, the file
+`package.json` should be updated with the dependencies and versions
+needed, then run
+
+	rm -rf node_modules; npm install
+
+to refresh the dependencies.
+
+
+before running the weinre server
+--------------------------------
+
+Before running the weinre server, after downloading the source,
+you will need to run a 'build'.
+
+
+running the weinre server
+-------------------------
+
diff --git a/weinre.server/lib/Channel.coffee b/weinre.server/lib/Channel.coffee
new file mode 100644
index 0000000..70f5841
--- /dev/null
+++ b/weinre.server/lib/Channel.coffee
@@ -0,0 +1,118 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils          = require './utils'
+channelManager = require './channelManager'
+messageHandler = require './messageHandler'
+MessageQueue   = require './MessageQueue'
+
+AnonymousId = 'anonymous'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class Channel
+    
+    #---------------------------------------------------------------------------
+    constructor: (@pathPrefix, @id, @remoteAddress, @isClient) ->
+        prefix         = if @isClient then 'c-' else 't-'
+        @name          = "#{prefix}#{utils.getNextSequenceNumber()}"
+        @messageQueue  = new MessageQueue
+        @isClosed      = false
+        @connections   = []
+        @isTarget      = !@isClient
+        @readTimeout   = utils.options.readTimeout * 1000
+        
+        @id = AnonymousId if !@id 
+        
+        @description = 
+            channel:       @name
+            id:            @id
+            hostName:      @remoteAddress
+            remoteAddress: @remoteAddress
+        
+        @updateLastRead()
+
+        channelManager.created @
+
+    #---------------------------------------------------------------------------
+    close: () ->
+        return if @isClosed
+        
+        channelManager.destroyed @
+        
+        @isClosed = true
+        @messageQueue.shutdown()
+
+    #---------------------------------------------------------------------------
+    sendCallback: (intfName, callbackId, args...) ->
+        return if !callbackId
+        
+        args.unshift callbackId
+        
+        @sendMessage intfName, 'sendCallback', args...
+        
+    #---------------------------------------------------------------------------
+    sendMessage: (intfName, method, args...) ->
+
+        message = genJSON
+            interface: intfName
+            method:    method
+            args:      args
+        
+        @messageQueue.push message
+
+    #---------------------------------------------------------------------------
+    handleMessages: (messages) ->
+
+        for message in messages
+            message = parseJSON(message)
+            continue if !message
+            
+            messageHandler.handleMessage @, message
+        
+    #---------------------------------------------------------------------------
+    getMessages: (callback) ->
+        @updateLastRead()
+        return callback.call(null, null) if @isClosed
+        
+        @messageQueue.pullAll @readTimeout, callback
+        
+    #---------------------------------------------------------------------------
+    updateLastRead: () ->
+        @lastRead = (new Date).valueOf()
+
+    #---------------------------------------------------------------------------
+    toString: () ->
+        connections = _.map(@connections, (val) -> val.name).join(',')
+        "Channel(#{@name}, closed:#{@isClosed}, connections:[#{connections}])"
+
+#-------------------------------------------------------------------------------
+parseJSON = (message) ->
+    try 
+        return JSON.parse(message)
+    catch e
+        return null
+
+#-------------------------------------------------------------------------------
+genJSON = (message) ->
+    try 
+        return JSON.stringify(message)
+    catch e
+        return null
diff --git a/weinre.server/lib/HttpChannelHandler.coffee b/weinre.server/lib/HttpChannelHandler.coffee
new file mode 100644
index 0000000..dd7f2f4
--- /dev/null
+++ b/weinre.server/lib/HttpChannelHandler.coffee
@@ -0,0 +1,154 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils          = require './utils'
+Channel        = require './Channel'
+channelManager = require './channelManager'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class HttpChannelHandler
+
+    #---------------------------------------------------------------------------
+    constructor: (@pathPrefix) ->
+    
+        if @pathPrefix == '/ws/client'
+            @isClient = true
+            
+        else if @pathPrefix == '/ws/target'
+            @isClient = false
+            
+        else
+            utils.pitch "invalid pathPrefix: #{@pathPrefix}"
+            
+        @isTarget = !@isClient
+        
+    #---------------------------------------------------------------------------
+    handle: (request, response, uri) ->
+    
+        setCORSHeaders  request, response
+        setCacheHeaders request, response
+
+        #-----------------
+        
+        # * #{pathPrefix}a
+        if uri[0] != '/'
+            return handleError(request, response, 404)
+            
+        #-----------------
+        
+        if uri == '/'
+        
+            # OPTIONS #{pathPrefix}/
+            if request.method == 'OPTIONS'
+                return handleOptions(request, response)
+
+            # POST #{pathPrefix}/
+            if request.method == 'POST'
+                return handleCreate(@pathPrefix, @isClient, request, response)
+                
+            # * #{pathPrefix}/
+            return handleError(request, response, 405)
+            
+        #-----------------
+            
+        parts = uri.split('/')
+        
+        # * #{pathPrefix}/x/y
+        if parts.length > 2
+            return handleError(request, response, 404)
+
+        #-----------------
+        
+        channelName = parts[1]
+        
+        # OPTIONS #{pathPrefix}/x
+        if request.method == 'OPTIONS'
+            return handleOptions(request, response)
+
+        # GET #{pathPrefix}/x
+        if request.method == 'GET'
+            return handleGet(request, response, channelName)
+        
+        # POST #{pathPrefix}/x
+        if request.method == 'POST'
+            return handlePost(request, response, channelName)
+        
+        # anything else
+        return handleError(request, response, 405)
+
+#-------------------------------------------------------------------------------
+handleCreate = (pathPrefix, isClient, request, response) ->
+    id = request.body?.id
+    
+    remoteAddress = request.connection?.remoteAddress || ""
+    
+    channel = new Channel(pathPrefix, id, remoteAddress, isClient)
+    
+    response.contentType 'application/json'
+    response.send JSON.stringify
+        channel: channel.name
+        id:      channel.id
+
+#-------------------------------------------------------------------------------
+handleGet = (request, response, channelName) ->
+    remoteAddress = request.connection?.remoteAddress || ""
+    channel       = channelManager.getChannel(channelName, remoteAddress)
+    return handleError(request, response, 404) if !channel
+    
+    channel.getMessages (messages) => 
+        return handleError(request, response, 404) if channel.isClosed
+        return handleError(request, response, 404) if !messages
+        
+        response.contentType 'application/json'
+        response.send JSON.stringify(messages)
+
+#-------------------------------------------------------------------------------
+handlePost = (request, response, channelName) ->
+    remoteAddress = request.connection?.remoteAddress || ""
+    channel       = channelManager.getChannel(channelName, remoteAddress)
+    return handleError(request, response, 404) if !channel
+    
+    channel.handleMessages(request.body)
+    response.send('')
+
+#-------------------------------------------------------------------------------
+handleOptions = (request, response) ->
+    response.send('')
+
+#-------------------------------------------------------------------------------
+handleError = (request, response, status) ->
+    response.send(status)
+
+#-------------------------------------------------------------------------------
+setCORSHeaders = (request, response) ->
+    origin = request.header 'Origin'
+    return if !origin
+    
+    response.header 'Access-Control-Allow-Origin',  origin
+    response.header 'Access-Control-Max-Age',       '600'
+    response.header 'Access-Control-Allow-Methods', 'GET, POST'
+
+#-------------------------------------------------------------------------------
+setCacheHeaders = (request, response) ->
+    response.header 'Pragma',        'no-cache'
+    response.header 'Expires',       '0'
+    response.header 'Cache-Control', 'no-cache'
+    response.header 'Cache-Control', 'no-store'
diff --git a/weinre.server/lib/MessageQueue.coffee b/weinre.server/lib/MessageQueue.coffee
new file mode 100644
index 0000000..52af9ea
--- /dev/null
+++ b/weinre.server/lib/MessageQueue.coffee
@@ -0,0 +1,87 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class MessageQueue
+
+    #---------------------------------------------------------------------------
+    constructor: () ->
+        @messages     = []
+        @closed       = false
+        @callback     = null
+        @timer        = null
+        
+        _.bindAll @, '_timerExpired', '_updated'
+        
+    #---------------------------------------------------------------------------
+    shutdown: () ->
+        return if @closed
+
+        @closed = true
+
+        clearTimeout @timer if @timer
+        @callback.call(null, @messages) if @callback
+        
+        @callback = null
+        @messages = null 
+        @timer    = null
+    
+    #---------------------------------------------------------------------------
+    push: (message) ->
+        return if @closed
+        
+        @messages.push message
+        process.nextTick @_updated
+
+    #---------------------------------------------------------------------------
+    pullAll: (timeout, callback) ->
+        return callback.call(null, null) if @closed
+        return callback.call(null, [])   if @callback
+        
+        if @messages.length
+            callback.call(null, @messages)
+            @messages = []
+            return
+        
+        @callback = callback
+        @timer    = setTimeout @_timerExpired, timeout
+
+    #---------------------------------------------------------------------------
+    _timerExpired: () ->
+        @_updated()
+        
+    #---------------------------------------------------------------------------
+    _updated: () ->
+        return if @closed
+        return if !@callback
+        
+        callback = @callback
+        messages = @messages
+        clearTimeout @timer if @timer
+        
+        @callback = null
+        @messages = []
+        @timer    = null
+
+        callback.call(null, messages)      
+
diff --git a/weinre.server/lib/channelManager.coffee b/weinre.server/lib/channelManager.coffee
new file mode 100644
index 0000000..48abca6
--- /dev/null
+++ b/weinre.server/lib/channelManager.coffee
@@ -0,0 +1,126 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_  = require 'underscore'
+
+utils          = require './utils'
+serviceManager = require './serviceManager'
+
+WeinreClientEvents = null
+WeinreTargetEvents = null
+
+channelManager = null
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ChannelManager
+
+    #---------------------------------------------------------------------------
+    constructor: () ->
+        @channels  = {}
+
+    #---------------------------------------------------------------------------
+    initialize: ->
+
+        WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+        WeinreTargetEvents = serviceManager.get 'WeinreTargetEvents'
+        
+        if !WeinreClientEvents
+            utils.exit 'WeinreClientEvents service not registered'
+
+        if !WeinreTargetEvents
+            utils.exit 'WeinreTargetEvents service not registered'
+
+    #---------------------------------------------------------------------------
+    created: (channel) ->
+        @channels[channel.name] = channel
+        
+    #---------------------------------------------------------------------------
+    destroyed: (channel) ->
+        if channel.isClient
+            for connection in channel.connections
+                @disconnectChannels(channel, connection)
+        else
+            for connection in channel.connections
+                @disconnectChannels(connection, channel)
+                
+        clients = @getClientChannels(channel.id)
+
+        if channel.isClient        
+            WeinreClientEvents.clientUnregistered(clients, channel.name)
+        else
+            WeinreClientEvents.targetUnregistered(clients, channel.name)
+
+        delete @channels[channel.name]    
+
+    #---------------------------------------------------------------------------
+    getChannel: (name, remoteAddress) ->
+        return null if !_.has(@channels, name)
+            
+        channel = @channels[name]
+
+        return null if !channel
+        
+        if remoteAddress
+            return null if channel.remoteAddress != remoteAddress
+        
+        channel
+
+    #---------------------------------------------------------------------------
+    connectChannels: (client, target) ->
+        return if client.isClosed or target.isClosed
+        
+        if client.connections.length
+            @disconnectChannels(client, client.connections[0])
+        
+        client.connections.push target
+        target.connections.push client
+        
+        clients = @getClientChannels(client.id)
+
+        WeinreClientEvents.connectionCreated(clients, client.name, target.name)
+        WeinreTargetEvents.connectionCreated(target,  client.name, target.name)
+        
+    #---------------------------------------------------------------------------
+    disconnectChannels: (client, target) ->
+
+        clients = @getClientChannels(client.id)
+
+        WeinreClientEvents.connectionDestroyed(clients, client.name, target.name)
+        WeinreTargetEvents.connectionDestroyed(target,  client.name, target.name)
+
+        client.connections = _.without(client.connections, target)
+        target.connections = _.without(target.connections, client)
+        
+    #---------------------------------------------------------------------------
+    getChannels: (id) ->
+        if id?
+            _.filter(@channels, (item) -> item.id == id)
+        else
+            _.values(@channels)
+
+    #---------------------------------------------------------------------------
+    getClientChannels: (id) ->
+        _.filter(@channels, (item) -> item.isClient && item.id == id)
+
+    #---------------------------------------------------------------------------
+    getTargetChannels: (id) ->
+        _.filter(@channels, (item) -> item.isTarget && item.id == id)
+
+#-------------------------------------------------------------------------------
+module.exports = new ChannelManager
diff --git a/weinre.server/lib/cli.coffee b/weinre.server/lib/cli.coffee
new file mode 100644
index 0000000..2598c68
--- /dev/null
+++ b/weinre.server/lib/cli.coffee
@@ -0,0 +1,130 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+fs   = require 'fs'
+path = require 'path'
+
+_     = require 'underscore'
+nopt  = require 'nopt'
+
+utils  = require './utils'
+weinre = require './weinre'
+
+optionDefaults = 
+    httpPort:     8080
+    boundHost:    'localhost'
+    verbose:      false
+    debug:        false
+    readTimeout:  5
+
+#-------------------------------------------------------------------------------
+exports.run = ->
+
+    knownOpts = 
+        httpPort:     Number
+        boundHost:    String
+        verbose:      Boolean
+        debug:        Boolean
+        readTimeout:  Number
+        deathTimeout: Number
+        help:         Boolean
+        
+    shortHands = 
+        '?':  ['--help']
+        'h':  ['--help']
+        
+    nopt.invalidHandler = printNoptError
+    parsedOpts = nopt(knownOpts, shortHands, process.argv, 2)
+    
+    #----
+
+    printHelp() if parsedOpts.help
+
+    args = parsedOpts.argv.remain
+
+    printHelp() if args.length != 0
+
+    #----
+    
+    delete parsedOpts.argv
+    opts = _.extend {}, optionDefaults, getDotWeinreServerProperties(), parsedOpts
+
+    if !opts.deathTimeout?
+        opts.deathTimeout = 3 * opts.readTimeout
+
+    utils.setOptions opts
+    
+    weinre.run opts
+
+#-------------------------------------------------------------------------------
+printNoptError = (key, val, types) ->
+    utils.exit "error with option '#{key}', value '#{val}'"
+
+#-------------------------------------------------------------------------------
+printHelp = () ->
+    version = weinre.getVersion()
+    
+    console.error """
+usage:   #{utils.Program} [options]
+version: #{version}
+
+options:
+    --httpPort     port to run the http server on        default: #{optionDefaults.httpPort}
+    --boundHost    ip address to bind the server to      default: #{optionDefaults.boundHost}
+    --verbose      print more diagnostics                default: #{optionDefaults.verbose}
+    --debug        print even more diagnostics           default: #{optionDefaults.debug}
+    --readTimeout  seconds to wait for a client message  default: #{optionDefaults.readTimeout}
+    --deathTimeout seconds to wait to kill client        default: 3*readTimeout
+    
+--boundHost can be an ip address, hostname, or -all-, where -all-
+means binding to all ip address on the current machine'
+
+for more info see: http://incubator.apache.org/callback/
+"""
+    process.exit()
+
+#-------------------------------------------------------------------------------
+getDotWeinreServerProperties = () ->
+    properties = {}
+    
+    fileName = replaceTilde '~/.weinre/server.properties'
+    return options if !path.existsSync(fileName) 
+    
+    contents = fs.readFileSync(fileName, 'utf8')
+    lines    = contents.split('\n')
+
+    for line in lines
+        line = line.replace(/#.*/,'')
+        match = line.match /\s*(\w+)\s*:\s*(.+)\s*/
+        continue if !match
+        
+        key = utils.trim match[1]
+        val = utils.trim match[2]
+        
+        properties[key] = val
+
+    properties
+
+#-------------------------------------------------------------------------------
+replaceTilde = (fileName) ->
+    fileName.replace('~', getTildeReplacement())
+
+#-------------------------------------------------------------------------------
+getTildeReplacement = () ->
+    process.env["HOME"] || process.env["USERPROFILE"] || '.'
diff --git a/weinre.server/lib/dumpingHandler.coffee b/weinre.server/lib/dumpingHandler.coffee
new file mode 100644
index 0000000..310852d
--- /dev/null
+++ b/weinre.server/lib/dumpingHandler.coffee
@@ -0,0 +1,77 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+dumpingHandler = (request, response, uri) ->
+    originalSend = response.send
+    response.send = (body) ->
+        dumpResponse(originalSend, body, request, response, uri)
+    
+    return if request.method != 'POST'
+    
+    utils.logVerbose '--------------------------------------------------'
+    utils.logVerbose "#{request.method} #{uri} [request]"
+    
+    if _.isArray(request.body)
+        for element in request.body
+            utils.logVerbose "   #{enhance(JSON.parse(element))}"
+    else
+        utils.logVerbose "   #{enhance(request.body)}"
+
+#-------------------------------------------------------------------------------
+dumpResponse = (originalSend, body, request, response, uri) ->
+    originalSend.call(response, body)
+
+    return if request.method not in ['GET', 'POST']
+
+    try 
+        body = JSON.parse(body)
+    catch e
+        return
+
+    return if _.isArray(body) && (body.length == 0)
+        
+    utils.logVerbose '--------------------------------------------------'
+    utils.logVerbose "#{request.method} #{uri} #{response.statusCode} [response]"
+    
+    if _.isArray(body)
+        for element in body
+            utils.logVerbose "   #{enhance(JSON.parse(element))}"
+    else
+        utils.logVerbose "   #{enhance(body)}"
+
+#-------------------------------------------------------------------------------
+enhance = (object) ->
+    if !object.interface || !object.method || !object.args 
+        return JSON.stringify(object)
+        
+    signature = "#{object.interface}.#{object.method}"
+
+    args = JSON.stringify(object.args)
+    if args.length > 500
+        args = "#{args.substr(0,50)}..."
+    
+    return "#{signature}(#{args})"
+
+#-------------------------------------------------------------------------------
+module.exports = dumpingHandler
diff --git a/weinre.server/lib/extensionManager.coffee b/weinre.server/lib/extensionManager.coffee
new file mode 100644
index 0000000..c367425
--- /dev/null
+++ b/weinre.server/lib/extensionManager.coffee
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ExtensionManager
+
+    #---------------------------------------------------------------------------
+    constructor: () ->
+        @extensions = []
+    
+#-------------------------------------------------------------------------------
+module.exports = new ExtensionManager
diff --git a/weinre.server/lib/jsonBodyParser.coffee b/weinre.server/lib/jsonBodyParser.coffee
new file mode 100644
index 0000000..58f755b
--- /dev/null
+++ b/weinre.server/lib/jsonBodyParser.coffee
@@ -0,0 +1,47 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+jsonBodyParser = -> 
+    return (request, response, next) -> parseBodyAsJSON(request, response, next)
+        
+#-------------------------------------------------------------------------------
+parseBodyAsJSON = (request, response, next) ->
+
+    return next() if request.body
+    
+    request.body = {}
+    
+    return next() if request.method != 'POST'
+    
+    request.setEncoding 'utf8'
+    
+    buffer = ''
+    request.on 'data', (chunk) -> buffer += chunk
+    request.on 'end', ->
+        return next() if '' == buffer
+
+        try 
+            request.body = JSON.parse(buffer)
+            next()
+        catch e
+            next(e)
+
+#-------------------------------------------------------------------------------
+module.exports = jsonBodyParser
diff --git a/weinre.server/lib/messageHandler.coffee b/weinre.server/lib/messageHandler.coffee
new file mode 100644
index 0000000..0c79430
--- /dev/null
+++ b/weinre.server/lib/messageHandler.coffee
@@ -0,0 +1,59 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+utils             = require './utils'
+channelManager    = require './channelManager'
+serviceManager    = require './serviceManager'
+
+#-------------------------------------------------------------------------------
+utils.registerClass class MessageHandler
+
+    #---------------------------------------------------------------------------
+    handleMessage: (channel, message) ->
+        @_serviceMethodInvoker(channel, message.interface, message.method, message.args)
+
+    #---------------------------------------------------------------------------
+    _serviceMethodInvoker: (channel, intfName, method, args) ->
+        methodSignature = "#{intfName}.#{method}()"
+        # utils.logVerbose "MessageHandler._serviceMethodInvoker(#{methodSignature})"
+
+        service = serviceManager.get(intfName)
+        
+        if !service
+            return @_redirectToConnections(channel, intfName, method, args)
+
+        args = args.slice()
+        args.unshift channel
+        
+        try 
+            service[method].apply(service, args)
+            
+        catch e
+            utils.log "error running service method #{methodSignature}: #{e}"
+            utils.log "stack:\n#{e.stack}"
+
+    #---------------------------------------------------------------------------
+    _redirectToConnections: (channel, intfName, method, args) ->
+        # utils.logVerbose "MessageHandler._redirectToConnections(#{channel.name}, #{intfName}, #{method})"
+
+        for connection in channel.connections
+            connection.sendMessage(intfName, method, args...)
+            
+#-------------------------------------------------------------------------------
+module.exports = new MessageHandler
diff --git a/weinre.server/lib/service/WeinreClientCommands.coffee b/weinre.server/lib/service/WeinreClientCommands.coffee
new file mode 100644
index 0000000..29fc575
--- /dev/null
+++ b/weinre.server/lib/service/WeinreClientCommands.coffee
@@ -0,0 +1,123 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+_ = require('underscore')
+
+utils              = require '../utils'
+channelManager     = require '../channelManager'
+serviceManager     = require '../serviceManager'
+extensionManager   = require '../extensionManager'
+
+WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class WeinreClientCommands
+
+    #---------------------------------------------------------------------------
+    registerClient: (channel, callbackId) ->
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId, channel.description)        
+
+        options = _.extend {}, utils.options
+        for own key, val of options
+            if typeof val in ['number', 'boolean']
+                options[key] = "#{val}"
+        
+        WeinreClientEvents.serverProperties(channel, options)
+
+        clients = channelManager.getClientChannels(channel.id)
+        WeinreClientEvents.clientRegistered(clients, channel.description)
+
+    #---------------------------------------------------------------------------
+    getTargets: (channel, callbackId) ->
+        channels = channelManager.getTargetChannels(channel.id)
+        result = _.pluck(channels, 'description')
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+    #---------------------------------------------------------------------------
+    getClients: (channel, callbackId) ->
+        channels = channelManager.getClientChannels(channel.id)
+        result = _.pluck(channels, 'description')
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+    #---------------------------------------------------------------------------
+    getExtensions: (channel, callbackId) ->
+        result = for extension in extensionManager.extensions
+            { startPage: "extensions/#{extension}/extension.html" }
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+    #---------------------------------------------------------------------------
+    connectTarget: (channel, clientName, targetName, callbackId) ->
+        client = channelManager.getChannel(clientName)
+        return if !client
+
+        target = channelManager.getChannel(targetName)
+        return if !target
+
+        channelManager.connectChannels(client, target)
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
+            
+    #---------------------------------------------------------------------------
+    disconnectTarget: (channel, clientName, callbackId) ->
+        client = connectionManager.getClient(clientName)
+        return if !client
+
+        target = client.getConnectedTarget()
+        return if !target
+
+        connectionManager.disconnect(client, target)
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
+            
+    #---------------------------------------------------------------------------
+    logDebug: (channel, message, callbackId) ->
+        utils.logVerbose "client #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
+            
+    #---------------------------------------------------------------------------
+    logInfo: (channel, message, callbackId) ->
+        utils.log "client #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
+            
+    #---------------------------------------------------------------------------
+    logWarning: (channel, message, callbackId) ->
+        utils.log "client #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
+            
+    #---------------------------------------------------------------------------
+    logError: (channel, message, callbackId) ->
+        utils.log "client #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreClientEvents.sendCallback(channel, callbackId)
diff --git a/weinre.server/lib/service/WeinreTargetCommands.coffee b/weinre.server/lib/service/WeinreTargetCommands.coffee
new file mode 100644
index 0000000..4603e20
--- /dev/null
+++ b/weinre.server/lib/service/WeinreTargetCommands.coffee
@@ -0,0 +1,90 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+utils              = require '../utils'
+channelManager     = require '../channelManager'
+serviceManager     = require '../serviceManager'
+
+WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+WeinreTargetEvents = serviceManager.get 'WeinreTargetEvents'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class WeinreTargetCommands
+
+    #---------------------------------------------------------------------------
+    registerTarget: (channel, url, callbackId) -> 
+        channel.description.url = url
+
+        clients = channelManager.getClientChannels(channel.id)
+        WeinreClientEvents.targetRegistered(clients, channel.description)
+    
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, channel.description)
+
+    #---------------------------------------------------------------------------
+    sendClientCallback: (channel, clientCallbackId, args, callbackId) ->
+
+        # the channel to send the callback to is embedded in the callbackId
+        callbackChannel = getCallbackChannel(clientCallbackId)
+        if !callbackChannel
+            return main.warn "#{@constructor.name}.sendClientCallback() sent with invalid callbackId: #{clientCallbackId}"
+
+        callbackChannel = channelManager.getChannel(callbackChannel)
+        if !callbackChannel
+            # indication that channel was closed; this message may generate a lot of noise
+            return main.warn "#{@constructor.name}.sendClientCallback() unable to find channel : #{clientCallbackId}"
+
+        WeinreClientEvents.sendCallback(callbackChannel, clientCallbackId, args)
+            
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+    #---------------------------------------------------------------------------
+    logDebug: (channel, message, callbackId) ->
+        utils.logVerbose "target #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+    #---------------------------------------------------------------------------
+    logInfo: (channel, message, callbackId) ->
+        utils.log "target #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+    #---------------------------------------------------------------------------
+    logWarning: (channel, message, callbackId) ->
+        utils.log "target #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+    #---------------------------------------------------------------------------
+    logError: (channel, message, callbackId) ->
+        utils.log "target #{channel.name}: #{message}"
+
+        if callbackId
+            WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+#---------------------------------------------------------------------------
+getCallbackChannel = (callbackId) ->
+    callbackId = callbackId.toString()
+    callbackId.split('::')[0]
+
diff --git a/weinre.server/lib/serviceManager.coffee b/weinre.server/lib/serviceManager.coffee
new file mode 100644
index 0000000..2a9f6c8
--- /dev/null
+++ b/weinre.server/lib/serviceManager.coffee
@@ -0,0 +1,95 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+path = require 'path'
+fs   = require 'fs'
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+Services = {}
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ServiceManager
+    
+    #---------------------------------------------------------------------------
+    constructor: ->
+        @services = {}
+
+    #---------------------------------------------------------------------------
+    get: (name) ->
+        return @services[name] if _.has(@services, name)
+        
+        null
+
+    #---------------------------------------------------------------------------
+    registerLocalClass: (name) ->
+
+        serviceClass = null
+        try
+            serviceClass = require "./service/#{name}"
+        catch e
+            utils.log "local service class not found: #{name}"
+            throw e
+
+        @services[name] = new serviceClass
+    
+    #---------------------------------------------------------------------------
+    registerProxyClass: (name) ->
+    
+        intf = getServiceInterface(name)
+        
+        if !intf
+            utils.exit "proxy service class not found: #{name}"
+            
+        if intf.name != name
+            utils.exit "proxy interface '#{intf.name}' loaded when '#{name}' requested"
+            
+        service = {}
+        
+        for method in intf.methods
+            service[method.name] = getMethodProxy(name, method.name)    
+            
+        @services[name] = service
+
+
+#-------------------------------------------------------------------------------
+getMethodProxy = (intfName, methodName) ->
+    (channels, args...) ->
+        channels = [channels] if !_.isArray(channels) 
+        
+        for channel in channels
+            channel.sendMessage(intfName, methodName, args...)
+    
+#-------------------------------------------------------------------------------
+getServiceInterface = (name) ->
+    jsonName = "#{name}.json"
+    fileName = path.join utils.options.staticWebDir, 'interfaces', jsonName
+    
+    return null if !path.existsSync(fileName) 
+    
+    contents = fs.readFileSync(fileName, 'utf8')
+    
+    serviceInterface = JSON.parse(contents)
+    
+    return serviceInterface.interfaces[0]
+
+#-------------------------------------------------------------------------------
+module.exports = new ServiceManager
\ No newline at end of file
diff --git a/weinre.server/lib/utils.coffee b/weinre.server/lib/utils.coffee
new file mode 100644
index 0000000..39bc5ab
--- /dev/null
+++ b/weinre.server/lib/utils.coffee
@@ -0,0 +1,187 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+path = require 'path'
+
+utils = exports
+
+utils.Program = Program = path.basename process.argv[1]
+
+SequenceNumberMax = 100 * 1024 * 1024
+SequenceNumber    = Math.floor(Math.random() * SequenceNumberMax)
+
+#-------------------------------------------------------------------------------
+utils.getNextSequenceNumber = (g) -> 
+    SequenceNumber++
+    
+    if SequenceNumber > SequenceNumberMax
+        SequenceNumber = 0
+        
+    SequenceNumber
+
+#-------------------------------------------------------------------------------
+utils.trim = (string) -> 
+    string.replace(/(^\s+)|(\s+$)/g,'')
+
+#-------------------------------------------------------------------------------
+utils.log = log = (message) ->
+    date    = new Date()
+    time    = date.toISOString()
+    console.log "#{time} #{Program}: #{message}"
+
+#-------------------------------------------------------------------------------
+utils.logVerbose = (message) ->
+    return if !utils?.options?.verbose
+
+    log message
+
+#-------------------------------------------------------------------------------
+utils.logDebug = (message) ->
+    return if !utils?.options?.debug
+
+    log message
+
+#-------------------------------------------------------------------------------
+utils.exit = (message) ->
+    log message
+    process.exit 1
+
+#-------------------------------------------------------------------------------
+utils.pitch = (message) ->
+    log message
+    throw message
+
+#-------------------------------------------------------------------------------
+utils.setOptions = (options) ->
+    utils.options = options
+    
+#-------------------------------------------------------------------------------
+utils.ensureInteger = (value, message) ->
+    newValue = parseInt value
+    
+    if isNaN newValue
+        utils.exit "#{message}: '#{value}'"
+    
+    newValue    
+    
+#-------------------------------------------------------------------------------
+utils.ensureString = (value, message) ->
+    
+    if typeof value != 'string'
+        utils.exit "#{message}: '#{value}'"
+    
+    value    
+    
+#-------------------------------------------------------------------------------
+utils.ensureBoolean = (value, message) ->
+    uValue = value.toString().toUpperCase()
+
+    newValue = null    
+    switch uValue
+        when 'TRUE'  then newValue = true
+        when 'FALSE' then newValue = false
+    
+    if typeof(newValue) != 'boolean'
+        utils.exit "#{message}: '#{value}'"
+    
+    newValue
+
+#-------------------------------------------------------------------------------
+utils.setNamesForClass = (aClass) ->
+
+    for own key, val of aClass
+        if typeof(val) is "function"
+            val.signature   = "#{aClass.name}::#{key}"
+            val.displayName = val.signature
+            val.name        = val.signature
+
+    for own key, val of aClass.prototype
+        if typeof(val) is "function"
+            val.signature   = "#{aClass.name}.#{key}"
+            val.displayName = val.signature
+            val.name        = val.signature
+
+#-------------------------------------------------------------------------------
+utils.registerClass = (aClass) ->
+    utils.setNamesForClass(aClass)
+    aClass
+
+#-------------------------------------------------------------------------------
+Error.prepareStackTrace = (error, structuredStackTrace) ->
+    result = []
+    result.push "---------------------------------------------------------"
+    result.push "error: #{error}"
+    result.push "---------------------------------------------------------"
+    result.push "stack: "
+
+    longestFile = 0
+    longestLine = 0
+    
+    for callSite in structuredStackTrace
+        file = callSite.getFileName()
+        line = callSite.getLineNumber()
+
+        file = path.basename(file)
+        line = "#{line}"
+        
+        if file.length > longestFile
+            longestFile = file.length
+    
+        if line.length > longestLine
+            longestLine = line.length
+    
+    for callSite in structuredStackTrace
+        func = callSite.getFunction()
+        file = callSite.getFileName()
+        line = callSite.getLineNumber()
+
+        file = path.basename(file)
+        line = "#{line}"
+        
+        file = alignRight(file, longestFile)
+        line = alignLeft( line, longestLine)
+        
+        funcName = func.displayName ||
+                   func.name || 
+                   callSite.getFunctionName()
+                   callSite.getMethodName()
+                   '???'
+        
+        if funcName == "Module._compile"
+            result.pop()
+            result.pop()
+            break
+            
+        result.push "   #{file}:#{line} - #{funcName}()"
+        
+    result.join "\n"
+
+#-------------------------------------------------------------------------------
+alignLeft = (string, length) ->
+    while string.length < length
+        string = "#{string} "
+        
+    string
+
+#-------------------------------------------------------------------------------
+alignRight = (string, length) ->
+    while string.length < length
+        string = " #{string}"
+
+    string
diff --git a/weinre.server/lib/weinre.coffee b/weinre.server/lib/weinre.coffee
new file mode 100644
index 0000000..a334596
--- /dev/null
+++ b/weinre.server/lib/weinre.coffee
@@ -0,0 +1,174 @@
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+fs   = require 'fs'
+net  = require 'net'
+dns  = require 'dns'
+path = require 'path'
+
+express = require 'express'
+
+utils              = require './utils'
+jsonBodyParser     = require './jsonBodyParser'
+HttpChannelHandler = require './HttpChannelHandler'
+dumpingHandler     = require './dumpingHandler'
+channelManager     = require './channelManager'
+serviceManager     = require './serviceManager'
+
+#-------------------------------------------------------------------------------
+exports.run = (options) ->
+    processOptions(options, run2)
+
+#-------------------------------------------------------------------------------
+run2 = ->
+    options = utils.options
+    
+    serviceManager.registerProxyClass 'WeinreClientEvents'
+    serviceManager.registerProxyClass 'WeinreTargetEvents'
+    serviceManager.registerLocalClass 'WeinreClientCommands'
+    serviceManager.registerLocalClass 'WeinreTargetCommands'
+    
+    startDeathWatcher options.deathTimeout
+    
+    startServer()    
+
+#-------------------------------------------------------------------------------
+processOptions = (options, cb) ->
+    options.httpPort     = utils.ensureInteger( options.httpPort,     'the value of the option httpPort is not a number')
+    options.boundHost    = utils.ensureString(  options.boundHost,    'the value of the option boundHost is not a string')
+    options.verbose      = utils.ensureBoolean( options.verbose,      'the value of the option verbose is not a boolean')
+    options.debug        = utils.ensureBoolean( options.debug,        'the value of the option debug is not a boolean')
+    options.readTimeout  = utils.ensureInteger( options.readTimeout,  'the value of the option readTimeout is not a number')
+    options.deathTimeout = utils.ensureInteger( options.deathTimeout, 'the value of the option deathTimeout is not a number')
+
+    options.verbose = true if options.debug
+    
+    options.staticWebDir = getStaticWebDir()
+    
+    utils.logVerbose "version:              #{getVersion()}"
+    utils.logVerbose "option httpPort:      #{options.httpPort}"
+    utils.logVerbose "option boundHost:     #{options.boundHost}"
+    utils.logVerbose "option verbose:       #{options.verbose}"
+    utils.logVerbose "option debug:         #{options.debug}"
+    utils.logVerbose "option readTimeout:   #{options.readTimeout}"
+    utils.logVerbose "option deathTimeout:  #{options.deathTimeout}"
+
+    utils.setOptions options
+
+    checkHost options.boundHost, (err) ->
+        if err
+            utils.exit "unable to resolve boundHost address: #{options.boundHost}"
+
+        cb()
+
+#-------------------------------------------------------------------------------
+checkHost = (hostName, cb) ->
+    return cb() if hostName == '-all-'
+    return cb() if hostName == 'localhost'
+    
+    return cb() if net.isIP(hostName)
+    
+    dns.lookup hostName, cb
+
+#-------------------------------------------------------------------------------
+deathTimeout = null
+
+#-------------------------------------------------------------------------------
+startDeathWatcher = (timeout) ->
+    deathTimeout = utils.options.deathTimeout * 1000
+    
+    setInterval checkForDeath, 1000
+
+#-------------------------------------------------------------------------------
+checkForDeath = ->
+    now = (new Date).valueOf()
+    for channel in channelManager.getChannels()
+        if now - channel.lastRead > deathTimeout
+            channel.close()
+
+#-------------------------------------------------------------------------------
+startServer = () ->
+    options = utils.options
+
+    clientHandler = new HttpChannelHandler('/ws/client')
+    targetHandler = new HttpChannelHandler('/ws/target')
+    
+    channelManager.initialize()
+    
+    favIcon = "#{options.staticWebDir}/images/weinre-icon-32x32.png"
+
+    staticCacheOptions =
+        maxObjects: 500
+        maxLength:  32 * 1024 * 1024
+        
+    app = express.createServer()
+    
+    app.on 'error', (error) ->
+        utils.exit "error running server: #{error}"
+
+    app.use express.favicon(favIcon)
+
+    app.use jsonBodyParser()
+
+    app.all /^\/ws\/client(.*)/, (request, response, next) ->
+        uri = request.params[0]
+        uri = '/' if uri == ''
+        
+        dumpingHandler(request, response, uri) if options.debug
+        clientHandler.handle(request, response, uri)
+
+    app.all /^\/ws\/target(.*)/, (request, response, next) ->
+        uri = request.params[0]
+        uri = '/' if uri == ''
+
+        dumpingHandler(request, response, uri) if options.debug
+        targetHandler.handle(request, response, uri)
+
+    app.use express.errorHandler(dumpExceptions: true)
+
+    app.use express.staticCache(staticCacheOptions)
+    app.use express.static(options.staticWebDir)
+    
+    if options.boundHost == '-all-'
+        utils.log "starting server at http://localhost:#{options.httpPort}"
+        app.listen options.httpPort
+        
+    else
+        utils.log "starting server at http://#{options.boundHost}:#{options.httpPort}"
+        app.listen options.httpPort, options.boundHost
+
+#-------------------------------------------------------------------------------
+getStaticWebDir = () ->
+    webDir = path.normalize path.join(__dirname,'../web')
+    return webDir if path.existsSync webDir
+    
+    utils.exit 'unable to find static files to serve in #{webDir}; did you do a build?'
+    
+#-------------------------------------------------------------------------------
+Version = null
+getVersion = exports.getVersion = () ->
+    return Version if Version 
+
+    packageJsonName  = path.join(path.dirname(fs.realpathSync(__filename)), '../package.json')
+
+    json = fs.readFileSync(packageJsonName, 'utf8')
+    values = JSON.parse(json)
+
+    Version = values.version
+    return Version
diff --git a/weinre.server/node_modules/.bin/cake b/weinre.server/node_modules/.bin/cake
new file mode 120000
index 0000000..d95f32a
--- /dev/null
+++ b/weinre.server/node_modules/.bin/cake
@@ -0,0 +1 @@
+../coffee-script/bin/cake
\ No newline at end of file
diff --git a/weinre.server/node_modules/.bin/coffee b/weinre.server/node_modules/.bin/coffee
new file mode 120000
index 0000000..b57f275
--- /dev/null
+++ b/weinre.server/node_modules/.bin/coffee
@@ -0,0 +1 @@
+../coffee-script/bin/coffee
\ No newline at end of file
diff --git a/weinre.server/node_modules/.bin/express b/weinre.server/node_modules/.bin/express
new file mode 120000
index 0000000..b741d99
--- /dev/null
+++ b/weinre.server/node_modules/.bin/express
@@ -0,0 +1 @@
+../express/bin/express
\ No newline at end of file
diff --git a/weinre.server/node_modules/.bin/nopt b/weinre.server/node_modules/.bin/nopt
new file mode 120000
index 0000000..6b6566e
--- /dev/null
+++ b/weinre.server/node_modules/.bin/nopt
@@ -0,0 +1 @@
+../nopt/bin/nopt.js
\ No newline at end of file
diff --git a/weinre.server/node_modules/coffee-script/.npmignore b/weinre.server/node_modules/coffee-script/.npmignore
new file mode 100644
index 0000000..21e430d
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/.npmignore
@@ -0,0 +1,11 @@
+*.coffee
+*.html
+.DS_Store
+.git*
+Cakefile
+documentation/
+examples/
+extras/coffee-script.js
+raw/
+src/
+test/
diff --git a/weinre.server/node_modules/coffee-script/LICENSE b/weinre.server/node_modules/coffee-script/LICENSE
new file mode 100644
index 0000000..8cb3cfd
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Jeremy Ashkenas
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.server/node_modules/coffee-script/README b/weinre.server/node_modules/coffee-script/README
new file mode 100644
index 0000000..69ee6f4
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/README
@@ -0,0 +1,51 @@
+
+            {
+         }   }   {
+        {   {  }  }
+         }   }{  {
+        {  }{  }  }                    _____       __  __
+       ( }{ }{  { )                   / ____|     / _|/ _|
+     .- { { }  { }} -.               | |     ___ | |_| |_ ___  ___
+    (  ( } { } { } }  )              | |    / _ \|  _|  _/ _ \/ _ \
+    |`-..________ ..-'|              | |___| (_) | | | ||  __/  __/
+    |                 |               \_____\___/|_| |_| \___|\___|
+    |                 ;--.
+    |                (__  \            _____           _       _
+    |                 | )  )          / ____|         (_)     | |
+    |                 |/  /          | (___   ___ _ __ _ _ __ | |_
+    |                 (  /            \___ \ / __| '__| | '_ \| __|
+    |                 |/              ____) | (__| |  | | |_) | |_
+    |                 |              |_____/ \___|_|  |_| .__/ \__|
+     `-.._________..-'                                  | |
+                                                        |_|
+
+
+  CoffeeScript is a little language that compiles into JavaScript.
+
+  Install Node.js, and then the CoffeeScript compiler:
+  sudo bin/cake install
+
+  Or, if you have the Node Package Manager installed:
+  npm install -g coffee-script
+  (Leave off the -g if you don't wish to install globally.)
+
+  Execute a script:
+  coffee /path/to/script.coffee
+
+  Compile a script:
+  coffee -c /path/to/script.coffee
+
+  For documentation, usage, and examples, see:
+  http://coffeescript.org/
+
+  To suggest a feature, report a bug, or general discussion:
+  http://github.com/jashkenas/coffee-script/issues/
+
+  If you'd like to chat, drop by #coffeescript on Freenode IRC,
+  or on webchat.freenode.net.
+
+  The source repository:
+  git://github.com/jashkenas/coffee-script.git
+
+  All contributors are listed here:
+  http://github.com/jashkenas/coffee-script/contributors
diff --git a/weinre.server/node_modules/coffee-script/Rakefile b/weinre.server/node_modules/coffee-script/Rakefile
new file mode 100644
index 0000000..dfb85da
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/Rakefile
@@ -0,0 +1,78 @@
+require 'rubygems'
+require 'erb'
+require 'fileutils'
+require 'rake/testtask'
+require 'json'
+
+desc "Build the documentation page"
+task :doc do
+  source = 'documentation/index.html.erb'
+  child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
+  at_exit { Process.kill("INT", child) }
+  Signal.trap("INT") { exit }
+  loop do
+    mtime = File.stat(source).mtime
+    if !@mtime || mtime > @mtime
+      rendered = ERB.new(File.read(source)).result(binding)
+      File.open('index.html', 'w+') {|f| f.write(rendered) }
+    end
+    @mtime = mtime
+    sleep 1
+  end
+end
+
+desc "Build coffee-script-source gem"
+task :gem do
+  require 'rubygems'
+  require 'rubygems/package'
+
+  gemspec = Gem::Specification.new do |s|
+    s.name      = 'coffee-script-source'
+    s.version   = JSON.parse(File.read('package.json'))["version"]
+    s.date      = Time.now.strftime("%Y-%m-%d")
+
+    s.homepage    = "http://jashkenas.github.com/coffee-script/"
+    s.summary     = "The CoffeeScript Compiler"
+    s.description = <<-EOS
+      CoffeeScript is a little language that compiles into JavaScript.
+      Underneath all of those embarrassing braces and semicolons,
+      JavaScript has always had a gorgeous object model at its heart.
+      CoffeeScript is an attempt to expose the good parts of JavaScript
+      in a simple way.
+    EOS
+
+    s.files = [
+      'lib/coffee_script/coffee-script.js',
+      'lib/coffee_script/source.rb'
+    ]
+
+    s.authors           = ['Jeremy Ashkenas']
+    s.email             = 'jashkenas@gmail.com'
+    s.rubyforge_project = 'coffee-script-source'
+  end
+
+  file = File.open("coffee-script-source.gem", "w")
+  Gem::Package.open(file, 'w') do |pkg|
+    pkg.metadata = gemspec.to_yaml
+
+    path = "lib/coffee_script/source.rb"
+    contents = <<-ERUBY
+module CoffeeScript
+  module Source
+    def self.bundled_path
+      File.expand_path("../coffee-script.js", __FILE__)
+    end
+  end
+end
+    ERUBY
+    pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+      tar_io.write(contents)
+    end
+
+    contents = File.read("extras/coffee-script.js")
+    path = "lib/coffee_script/coffee-script.js"
+    pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+      tar_io.write(contents)
+    end
+  end
+end
diff --git a/weinre.server/node_modules/coffee-script/bin/cake b/weinre.server/node_modules/coffee-script/bin/cake
new file mode 100755
index 0000000..5965f4e
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/bin/cake
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs   = require('fs');
+var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/coffee-script/cake').run();
diff --git a/weinre.server/node_modules/coffee-script/bin/coffee b/weinre.server/node_modules/coffee-script/bin/coffee
new file mode 100755
index 0000000..3d1d71c
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/bin/coffee
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs   = require('fs');
+var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/coffee-script/command').run();
diff --git a/weinre.server/node_modules/coffee-script/extras/jsl.conf b/weinre.server/node_modules/coffee-script/extras/jsl.conf
new file mode 100644
index 0000000..1190da5
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/extras/jsl.conf
@@ -0,0 +1,44 @@
+# JavaScriptLint configuration file for CoffeeScript.
+
++no_return_value              # function {0} does not always return a value
++duplicate_formal             # duplicate formal argument {0}
+-equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg                # variable {0} hides argument
++redeclared_var               # redeclaration of {0} {1}
+-anon_no_return_value         # anonymous function does not always return a value
++missing_semicolon            # missing semicolon
++meaningless_block            # meaningless block; curly braces have no impact
+-comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
++unreachable_code             # unreachable code
++missing_break                # missing break statement
+-missing_break_for_last_case  # missing break statement for last case in switch
+-comparison_type_conv         # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+-inc_dec_within_stmt          # increment (++) and decrement (--) operators used as part of greater statement
+-useless_void                 # use of the void type may be unnecessary (void is always undefined)
++multiple_plus_minus          # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label                 # use of label
+-block_without_braces         # block statement without curly braces
++leading_decimal_point        # leading decimal point may indicate a number or an object member
++trailing_decimal_point       # trailing decimal point may indicate a number or an object member
++octal_number                 # leading zeros make an octal number
++nested_comment               # nested comment
++misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
++ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement              # empty statement or extra semicolon
+-missing_option_explicit      # the "option explicit" control comment is missing
++partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit          # duplicate "option explicit" control comment
++useless_assign               # useless assignment
++ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+-missing_default_case         # missing default case in switch statement
++duplicate_case_in_switch     # duplicate case in switch statements
++default_not_at_end           # the default case is not at the end of the switch statement
++legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison           # useless comparison; comparing identical expressions
++with_statement               # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array      # extra comma is not recommended in array initializers
++assign_to_function_call      # assignment to a function call
++parseint_missing_radix       # parseInt missing radix parameter
++lambda_assign_requires_semicolon
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/browser.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/browser.js
new file mode 100644
index 0000000..ec2e479
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/browser.js
@@ -0,0 +1,74 @@
+(function() {
+  var CoffeeScript, runScripts;
+
+  CoffeeScript = require('./coffee-script');
+
+  CoffeeScript.require = require;
+
+  CoffeeScript.eval = function(code, options) {
+    return eval(CoffeeScript.compile(code, options));
+  };
+
+  CoffeeScript.run = function(code, options) {
+    if (options == null) options = {};
+    options.bare = true;
+    return Function(CoffeeScript.compile(code, options))();
+  };
+
+  if (typeof window === "undefined" || window === null) return;
+
+  CoffeeScript.load = function(url, callback) {
+    var xhr;
+    xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
+    xhr.open('GET', url, true);
+    if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
+    xhr.onreadystatechange = function() {
+      var _ref;
+      if (xhr.readyState === 4) {
+        if ((_ref = xhr.status) === 0 || _ref === 200) {
+          CoffeeScript.run(xhr.responseText);
+        } else {
+          throw new Error("Could not load " + url);
+        }
+        if (callback) return callback();
+      }
+    };
+    return xhr.send(null);
+  };
+
+  runScripts = function() {
+    var coffees, execute, index, length, s, scripts;
+    scripts = document.getElementsByTagName('script');
+    coffees = (function() {
+      var _i, _len, _results;
+      _results = [];
+      for (_i = 0, _len = scripts.length; _i < _len; _i++) {
+        s = scripts[_i];
+        if (s.type === 'text/coffeescript') _results.push(s);
+      }
+      return _results;
+    })();
+    index = 0;
+    length = coffees.length;
+    (execute = function() {
+      var script;
+      script = coffees[index++];
+      if ((script != null ? script.type : void 0) === 'text/coffeescript') {
+        if (script.src) {
+          return CoffeeScript.load(script.src, execute);
+        } else {
+          CoffeeScript.run(script.innerHTML);
+          return execute();
+        }
+      }
+    })();
+    return null;
+  };
+
+  if (window.addEventListener) {
+    addEventListener('DOMContentLoaded', runScripts, false);
+  } else {
+    attachEvent('onload', runScripts);
+  }
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/cake.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/cake.js
new file mode 100644
index 0000000..986d5cc
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/cake.js
@@ -0,0 +1,99 @@
+(function() {
+  var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
+
+  fs = require('fs');
+
+  path = require('path');
+
+  helpers = require('./helpers');
+
+  optparse = require('./optparse');
+
+  CoffeeScript = require('./coffee-script');
+
+  tasks = {};
+
+  options = {};
+
+  switches = [];
+
+  oparse = null;
+
+  helpers.extend(global, {
+    task: function(name, description, action) {
+      var _ref;
+      if (!action) {
+        _ref = [description, action], action = _ref[0], description = _ref[1];
+      }
+      return tasks[name] = {
+        name: name,
+        description: description,
+        action: action
+      };
+    },
+    option: function(letter, flag, description) {
+      return switches.push([letter, flag, description]);
+    },
+    invoke: function(name) {
+      if (!tasks[name]) missingTask(name);
+      return tasks[name].action(options);
+    }
+  });
+
+  exports.run = function() {
+    var arg, args, _i, _len, _ref, _results;
+    global.__originalDirname = fs.realpathSync('.');
+    process.chdir(cakefileDirectory(__originalDirname));
+    args = process.argv.slice(2);
+    CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
+      filename: 'Cakefile'
+    });
+    oparse = new optparse.OptionParser(switches);
+    if (!args.length) return printTasks();
+    try {
+      options = oparse.parse(args);
+    } catch (e) {
+      return fatalError("" + e);
+    }
+    _ref = options.arguments;
+    _results = [];
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      arg = _ref[_i];
+      _results.push(invoke(arg));
+    }
+    return _results;
+  };
+
+  printTasks = function() {
+    var cakefilePath, desc, name, spaces, task;
+    cakefilePath = path.join(path.relative(__originalDirname, process.cwd()), 'Cakefile');
+    console.log("" + cakefilePath + " defines the following tasks:\n");
+    for (name in tasks) {
+      task = tasks[name];
+      spaces = 20 - name.length;
+      spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
+      desc = task.description ? "# " + task.description : '';
+      console.log("cake " + name + spaces + " " + desc);
+    }
+    if (switches.length) return console.log(oparse.help());
+  };
+
+  fatalError = function(message) {
+    console.error(message + '\n');
+    console.log('To see a list of all tasks/options, run "cake"');
+    return process.exit(1);
+  };
+
+  missingTask = function(task) {
+    return fatalError("No such task: " + task);
+  };
+
+  cakefileDirectory = function(dir) {
+    var parent;
+    if (path.existsSync(path.join(dir, 'Cakefile'))) return dir;
+    parent = path.normalize(path.join(dir, '..'));
+    if (parent !== dir) return cakefileDirectory(parent);
+    throw new Error("Cakefile not found in " + (process.cwd()));
+  };
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/coffee-script.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/coffee-script.js
new file mode 100644
index 0000000..fd410ba
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/coffee-script.js
@@ -0,0 +1,150 @@
+(function() {
+  var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref,
+    __hasProp = Object.prototype.hasOwnProperty;
+
+  fs = require('fs');
+
+  path = require('path');
+
+  _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
+
+  parser = require('./parser').parser;
+
+  vm = require('vm');
+
+  if (require.extensions) {
+    require.extensions['.coffee'] = function(module, filename) {
+      var content;
+      content = compile(fs.readFileSync(filename, 'utf8'), {
+        filename: filename
+      });
+      return module._compile(content, filename);
+    };
+  } else if (require.registerExtension) {
+    require.registerExtension('.coffee', function(content) {
+      return compile(content);
+    });
+  }
+
+  exports.VERSION = '1.2.0';
+
+  exports.RESERVED = RESERVED;
+
+  exports.helpers = require('./helpers');
+
+  exports.compile = compile = function(code, options) {
+    var merge;
+    if (options == null) options = {};
+    merge = exports.helpers.merge;
+    try {
+      return (parser.parse(lexer.tokenize(code))).compile(merge({}, options));
+    } catch (err) {
+      if (options.filename) {
+        err.message = "In " + options.filename + ", " + err.message;
+      }
+      throw err;
+    }
+  };
+
+  exports.tokens = function(code, options) {
+    return lexer.tokenize(code, options);
+  };
+
+  exports.nodes = function(source, options) {
+    if (typeof source === 'string') {
+      return parser.parse(lexer.tokenize(source, options));
+    } else {
+      return parser.parse(source);
+    }
+  };
+
+  exports.run = function(code, options) {
+    var mainModule;
+    mainModule = require.main;
+    mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
+    mainModule.moduleCache && (mainModule.moduleCache = {});
+    mainModule.paths = require('module')._nodeModulePaths(path.dirname(options.filename));
+    if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
+      return mainModule._compile(compile(code, options), mainModule.filename);
+    } else {
+      return mainModule._compile(code, mainModule.filename);
+    }
+  };
+
+  exports.eval = function(code, options) {
+    var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _require;
+    if (options == null) options = {};
+    if (!(code = code.trim())) return;
+    Script = vm.Script;
+    if (Script) {
+      if (options.sandbox != null) {
+        if (options.sandbox instanceof Script.createContext().constructor) {
+          sandbox = options.sandbox;
+        } else {
+          sandbox = Script.createContext();
+          _ref2 = options.sandbox;
+          for (k in _ref2) {
+            if (!__hasProp.call(_ref2, k)) continue;
+            v = _ref2[k];
+            sandbox[k] = v;
+          }
+        }
+        sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
+      } else {
+        sandbox = global;
+      }
+      sandbox.__filename = options.filename || 'eval';
+      sandbox.__dirname = path.dirname(sandbox.__filename);
+      if (!(sandbox !== global || sandbox.module || sandbox.require)) {
+        Module = require('module');
+        sandbox.module = _module = new Module(options.modulename || 'eval');
+        sandbox.require = _require = function(path) {
+          return Module._load(path, _module, true);
+        };
+        _module.filename = sandbox.__filename;
+        _ref3 = Object.getOwnPropertyNames(require);
+        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+          r = _ref3[_i];
+          if (r !== 'paths') _require[r] = require[r];
+        }
+        _require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
+        _require.resolve = function(request) {
+          return Module._resolveFilename(request, _module);
+        };
+      }
+    }
+    o = {};
+    for (k in options) {
+      if (!__hasProp.call(options, k)) continue;
+      v = options[k];
+      o[k] = v;
+    }
+    o.bare = true;
+    js = compile(code, o);
+    if (sandbox === global) {
+      return vm.runInThisContext(js);
+    } else {
+      return vm.runInContext(js, sandbox);
+    }
+  };
+
+  lexer = new Lexer;
+
+  parser.lexer = {
+    lex: function() {
+      var tag, _ref2;
+      _ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
+      return tag;
+    },
+    setInput: function(tokens) {
+      this.tokens = tokens;
+      return this.pos = 0;
+    },
+    upcomingInput: function() {
+      return "";
+    }
+  };
+
+  parser.yy = require('./nodes');
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/command.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/command.js
new file mode 100644
index 0000000..da330b3
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/command.js
@@ -0,0 +1,442 @@
+(function() {
+  var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, joinTimeout, lint, loadRequires, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref;
+
+  fs = require('fs');
+
+  path = require('path');
+
+  helpers = require('./helpers');
+
+  optparse = require('./optparse');
+
+  CoffeeScript = require('./coffee-script');
+
+  _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
+
+  EventEmitter = require('events').EventEmitter;
+
+  helpers.extend(CoffeeScript, new EventEmitter);
+
+  printLine = function(line) {
+    return process.stdout.write(line + '\n');
+  };
+
+  printWarn = function(line) {
+    return process.stderr.write(line + '\n');
+  };
+
+  BANNER = 'Usage: coffee [options] path/to/script.coffee\n\nIf called without options, `coffee` will run your script.';
+
+  SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
+
+  opts = {};
+
+  sources = [];
+
+  sourceCode = [];
+
+  notSources = {};
+
+  watchers = {};
+
+  optionParser = null;
+
+  exports.run = function() {
+    var source, _i, _len, _results;
+    parseOptions();
+    if (opts.nodejs) return forkNode();
+    if (opts.help) return usage();
+    if (opts.version) return version();
+    if (opts.require) loadRequires();
+    if (opts.interactive) return require('./repl');
+    if (opts.watch && !fs.watch) {
+      printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + ".");
+    }
+    if (opts.stdio) return compileStdio();
+    if (opts.eval) return compileScript(null, sources[0]);
+    if (!sources.length) return require('./repl');
+    if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
+    process.argv = process.argv.slice(0, 2).concat(opts.literals);
+    process.argv[0] = 'coffee';
+    process.execPath = require.main.filename;
+    _results = [];
+    for (_i = 0, _len = sources.length; _i < _len; _i++) {
+      source = sources[_i];
+      _results.push(compilePath(source, true, path.normalize(source)));
+    }
+    return _results;
+  };
+
+  compilePath = function(source, topLevel, base) {
+    return fs.stat(source, function(err, stats) {
+      if (err && err.code !== 'ENOENT') throw err;
+      if ((err != null ? err.code : void 0) === 'ENOENT') {
+        if (topLevel && source.slice(-7) !== '.coffee') {
+          source = sources[sources.indexOf(source)] = "" + source + ".coffee";
+          return compilePath(source, topLevel, base);
+        }
+        if (topLevel) {
+          console.error("File not found: " + source);
+          process.exit(1);
+        }
+        return;
+      }
+      if (stats.isDirectory()) {
+        if (opts.watch) watchDir(source, base);
+        return fs.readdir(source, function(err, files) {
+          var file, index, _i, _len, _ref2, _results;
+          if (err && err.code !== 'ENOENT') throw err;
+          if ((err != null ? err.code : void 0) === 'ENOENT') return;
+          files = files.map(function(file) {
+            return path.join(source, file);
+          });
+          index = sources.indexOf(source);
+          [].splice.apply(sources, [index, index - index + 1].concat(files)), files;
+          [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() {
+            return null;
+          }))), _ref2;
+          _results = [];
+          for (_i = 0, _len = files.length; _i < _len; _i++) {
+            file = files[_i];
+            _results.push(compilePath(file, false, base));
+          }
+          return _results;
+        });
+      } else if (topLevel || path.extname(source) === '.coffee') {
+        if (opts.watch) watch(source, base);
+        return fs.readFile(source, function(err, code) {
+          if (err && err.code !== 'ENOENT') throw err;
+          if ((err != null ? err.code : void 0) === 'ENOENT') return;
+          return compileScript(source, code.toString(), base);
+        });
+      } else {
+        notSources[source] = true;
+        return removeSource(source, base);
+      }
+    });
+  };
+
+  compileScript = function(file, input, base) {
+    var o, options, t, task;
+    o = opts;
+    options = compileOptions(file);
+    try {
+      t = task = {
+        file: file,
+        input: input,
+        options: options
+      };
+      CoffeeScript.emit('compile', task);
+      if (o.tokens) {
+        return printTokens(CoffeeScript.tokens(t.input));
+      } else if (o.nodes) {
+        return printLine(CoffeeScript.nodes(t.input).toString().trim());
+      } else if (o.run) {
+        return CoffeeScript.run(t.input, t.options);
+      } else if (o.join && t.file !== o.join) {
+        sourceCode[sources.indexOf(t.file)] = t.input;
+        return compileJoin();
+      } else {
+        t.output = CoffeeScript.compile(t.input, t.options);
+        CoffeeScript.emit('success', task);
+        if (o.print) {
+          return printLine(t.output.trim());
+        } else if (o.compile) {
+          return writeJs(t.file, t.output, base);
+        } else if (o.lint) {
+          return lint(t.file, t.output);
+        }
+      }
+    } catch (err) {
+      CoffeeScript.emit('failure', err, task);
+      if (CoffeeScript.listeners('failure').length) return;
+      if (o.watch) return printLine(err.message);
+      printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
+      return process.exit(1);
+    }
+  };
+
+  compileStdio = function() {
+    var code, stdin;
+    code = '';
+    stdin = process.openStdin();
+    stdin.on('data', function(buffer) {
+      if (buffer) return code += buffer.toString();
+    });
+    return stdin.on('end', function() {
+      return compileScript(null, code);
+    });
+  };
+
+  joinTimeout = null;
+
+  compileJoin = function() {
+    if (!opts.join) return;
+    if (!sourceCode.some(function(code) {
+      return code === null;
+    })) {
+      clearTimeout(joinTimeout);
+      return joinTimeout = wait(100, function() {
+        return compileScript(opts.join, sourceCode.join('\n'), opts.join);
+      });
+    }
+  };
+
+  loadRequires = function() {
+    var realFilename, req, _i, _len, _ref2;
+    realFilename = module.filename;
+    module.filename = '.';
+    _ref2 = opts.require;
+    for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+      req = _ref2[_i];
+      require(req);
+    }
+    return module.filename = realFilename;
+  };
+
+  watch = function(source, base) {
+    var callback, compile, compileTimeout, prevStats, watchErr, watcher;
+    prevStats = null;
+    compileTimeout = null;
+    watchErr = function(e) {
+      if (e.code === 'ENOENT') {
+        if (sources.indexOf(source) === -1) return;
+        removeSource(source, base, true);
+        return compileJoin();
+      } else {
+        throw e;
+      }
+    };
+    compile = function() {
+      clearTimeout(compileTimeout);
+      return compileTimeout = wait(25, function() {
+        return fs.stat(source, function(err, stats) {
+          if (err) return watchErr(err);
+          if (prevStats && (stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime())) {
+            return;
+          }
+          prevStats = stats;
+          return fs.readFile(source, function(err, code) {
+            if (err) return watchErr(err);
+            return compileScript(source, code.toString(), base);
+          });
+        });
+      });
+    };
+    watchErr = function(e) {
+      if (e.code !== 'ENOENT') throw e;
+      removeSource(source, base, true);
+      return compileJoin();
+    };
+    try {
+      return watcher = fs.watch(source, callback = function(event) {
+        if (event === 'change') {
+          return compile();
+        } else if (event === 'rename') {
+          watcher.close();
+          return wait(250, function() {
+            compile();
+            try {
+              return watcher = fs.watch(source, callback);
+            } catch (e) {
+              return watchErr(e);
+            }
+          });
+        }
+      });
+    } catch (e) {
+      return watchErr(e);
+    }
+  };
+
+  watchDir = function(source, base) {
+    var readdirTimeout, watcher;
+    readdirTimeout = null;
+    try {
+      return watcher = fs.watch(source, function() {
+        clearTimeout(readdirTimeout);
+        return readdirTimeout = wait(25, function() {
+          return fs.readdir(source, function(err, files) {
+            var file, _i, _len, _results;
+            if (err) {
+              if (err.code !== 'ENOENT') throw err;
+              watcher.close();
+              return unwatchDir(source, base);
+            }
+            files = files.map(function(file) {
+              return path.join(source, file);
+            });
+            _results = [];
+            for (_i = 0, _len = files.length; _i < _len; _i++) {
+              file = files[_i];
+              if (!(!notSources[file])) continue;
+              if (sources.some(function(s) {
+                return s.indexOf(file) >= 0;
+              })) {
+                continue;
+              }
+              sources.push(file);
+              sourceCode.push(null);
+              _results.push(compilePath(file, false, base));
+            }
+            return _results;
+          });
+        });
+      });
+    } catch (e) {
+      if (e.code !== 'ENOENT') throw e;
+    }
+  };
+
+  unwatchDir = function(source, base) {
+    var file, prevSources, toRemove, _i, _len;
+    prevSources = sources.slice();
+    toRemove = (function() {
+      var _i, _len, _results;
+      _results = [];
+      for (_i = 0, _len = sources.length; _i < _len; _i++) {
+        file = sources[_i];
+        if (file.indexOf(source) >= 0) _results.push(file);
+      }
+      return _results;
+    })();
+    for (_i = 0, _len = toRemove.length; _i < _len; _i++) {
+      file = toRemove[_i];
+      removeSource(file, base, true);
+    }
+    if (!sources.some(function(s, i) {
+      return prevSources[i] !== s;
+    })) {
+      return;
+    }
+    return compileJoin();
+  };
+
+  removeSource = function(source, base, removeJs) {
+    var index, jsPath;
+    index = sources.indexOf(source);
+    sources.splice(index, 1);
+    sourceCode.splice(index, 1);
+    if (removeJs && !opts.join) {
+      jsPath = outputPath(source, base);
+      return path.exists(jsPath, function(exists) {
+        if (exists) {
+          return fs.unlink(jsPath, function(err) {
+            if (err && err.code !== 'ENOENT') throw err;
+            return timeLog("removed " + source);
+          });
+        }
+      });
+    }
+  };
+
+  outputPath = function(source, base) {
+    var baseDir, dir, filename, srcDir;
+    filename = path.basename(source, path.extname(source)) + '.js';
+    srcDir = path.dirname(source);
+    baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
+    dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
+    return path.join(dir, filename);
+  };
+
+  writeJs = function(source, js, base) {
+    var compile, jsDir, jsPath;
+    jsPath = outputPath(source, base);
+    jsDir = path.dirname(jsPath);
+    compile = function() {
+      if (js.length <= 0) js = ' ';
+      return fs.writeFile(jsPath, js, function(err) {
+        if (err) {
+          return printLine(err.message);
+        } else if (opts.compile && opts.watch) {
+          return timeLog("compiled " + source);
+        }
+      });
+    };
+    return path.exists(jsDir, function(exists) {
+      if (exists) {
+        return compile();
+      } else {
+        return exec("mkdir -p " + jsDir, compile);
+      }
+    });
+  };
+
+  wait = function(milliseconds, func) {
+    return setTimeout(func, milliseconds);
+  };
+
+  timeLog = function(message) {
+    return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
+  };
+
+  lint = function(file, js) {
+    var conf, jsl, printIt;
+    printIt = function(buffer) {
+      return printLine(file + ':\t' + buffer.toString().trim());
+    };
+    conf = __dirname + '/../../extras/jsl.conf';
+    jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
+    jsl.stdout.on('data', printIt);
+    jsl.stderr.on('data', printIt);
+    jsl.stdin.write(js);
+    return jsl.stdin.end();
+  };
+
+  printTokens = function(tokens) {
+    var strings, tag, token, value;
+    strings = (function() {
+      var _i, _len, _ref2, _results;
+      _results = [];
+      for (_i = 0, _len = tokens.length; _i < _len; _i++) {
+        token = tokens[_i];
+        _ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
+        _results.push("[" + tag + " " + value + "]");
+      }
+      return _results;
+    })();
+    return printLine(strings.join(' '));
+  };
+
+  parseOptions = function() {
+    var i, o, source, _len;
+    optionParser = new optparse.OptionParser(SWITCHES, BANNER);
+    o = opts = optionParser.parse(process.argv.slice(2));
+    o.compile || (o.compile = !!o.output);
+    o.run = !(o.compile || o.print || o.lint);
+    o.print = !!(o.print || (o.eval || o.stdio && o.compile));
+    sources = o.arguments;
+    for (i = 0, _len = sources.length; i < _len; i++) {
+      source = sources[i];
+      sourceCode[i] = null;
+    }
+  };
+
+  compileOptions = function(filename) {
+    return {
+      filename: filename,
+      bare: opts.bare
+    };
+  };
+
+  forkNode = function() {
+    var args, nodeArgs;
+    nodeArgs = opts.nodejs.split(/\s+/);
+    args = process.argv.slice(1);
+    args.splice(args.indexOf('--nodejs'), 2);
+    return spawn(process.execPath, nodeArgs.concat(args), {
+      cwd: process.cwd(),
+      env: process.env,
+      customFds: [0, 1, 2]
+    });
+  };
+
+  usage = function() {
+    return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
+  };
+
+  version = function() {
+    return printLine("CoffeeScript version " + CoffeeScript.VERSION);
+  };
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/grammar.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/grammar.js
new file mode 100644
index 0000000..2424fc7
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/grammar.js
@@ -0,0 +1,592 @@
+(function() {
+  var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
+
+  Parser = require('jison').Parser;
+
+  unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
+
+  o = function(patternString, action, options) {
+    var match;
+    patternString = patternString.replace(/\s{2,}/g, ' ');
+    if (!action) return [patternString, '$$ = $1;', options];
+    action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
+    action = action.replace(/\bnew /g, '$&yy.');
+    action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
+    return [patternString, "$$ = " + action + ";", options];
+  };
+
+  grammar = {
+    Root: [
+      o('', function() {
+        return new Block;
+      }), o('Body'), o('Block TERMINATOR')
+    ],
+    Body: [
+      o('Line', function() {
+        return Block.wrap([$1]);
+      }), o('Body TERMINATOR Line', function() {
+        return $1.push($3);
+      }), o('Body TERMINATOR')
+    ],
+    Line: [o('Expression'), o('Statement')],
+    Statement: [
+      o('Return'), o('Comment'), o('STATEMENT', function() {
+        return new Literal($1);
+      })
+    ],
+    Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')],
+    Block: [
+      o('INDENT OUTDENT', function() {
+        return new Block;
+      }), o('INDENT Body OUTDENT', function() {
+        return $2;
+      })
+    ],
+    Identifier: [
+      o('IDENTIFIER', function() {
+        return new Literal($1);
+      })
+    ],
+    AlphaNumeric: [
+      o('NUMBER', function() {
+        return new Literal($1);
+      }), o('STRING', function() {
+        return new Literal($1);
+      })
+    ],
+    Literal: [
+      o('AlphaNumeric'), o('JS', function() {
+        return new Literal($1);
+      }), o('REGEX', function() {
+        return new Literal($1);
+      }), o('DEBUGGER', function() {
+        return new Literal($1);
+      }), o('BOOL', function() {
+        var val;
+        val = new Literal($1);
+        if ($1 === 'undefined') val.isUndefined = true;
+        return val;
+      })
+    ],
+    Assign: [
+      o('Assignable = Expression', function() {
+        return new Assign($1, $3);
+      }), o('Assignable = TERMINATOR Expression', function() {
+        return new Assign($1, $4);
+      }), o('Assignable = INDENT Expression OUTDENT', function() {
+        return new Assign($1, $4);
+      })
+    ],
+    AssignObj: [
+      o('ObjAssignable', function() {
+        return new Value($1);
+      }), o('ObjAssignable : Expression', function() {
+        return new Assign(new Value($1), $3, 'object');
+      }), o('ObjAssignable :\
+       INDENT Expression OUTDENT', function() {
+        return new Assign(new Value($1), $4, 'object');
+      }), o('Comment')
+    ],
+    ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
+    Return: [
+      o('RETURN Expression', function() {
+        return new Return($2);
+      }), o('RETURN', function() {
+        return new Return;
+      })
+    ],
+    Comment: [
+      o('HERECOMMENT', function() {
+        return new Comment($1);
+      })
+    ],
+    Code: [
+      o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
+        return new Code($2, $5, $4);
+      }), o('FuncGlyph Block', function() {
+        return new Code([], $2, $1);
+      })
+    ],
+    FuncGlyph: [
+      o('->', function() {
+        return 'func';
+      }), o('=>', function() {
+        return 'boundfunc';
+      })
+    ],
+    OptComma: [o(''), o(',')],
+    ParamList: [
+      o('', function() {
+        return [];
+      }), o('Param', function() {
+        return [$1];
+      }), o('ParamList , Param', function() {
+        return $1.concat($3);
+      })
+    ],
+    Param: [
+      o('ParamVar', function() {
+        return new Param($1);
+      }), o('ParamVar ...', function() {
+        return new Param($1, null, true);
+      }), o('ParamVar = Expression', function() {
+        return new Param($1, $3);
+      })
+    ],
+    ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
+    Splat: [
+      o('Expression ...', function() {
+        return new Splat($1);
+      })
+    ],
+    SimpleAssignable: [
+      o('Identifier', function() {
+        return new Value($1);
+      }), o('Value Accessor', function() {
+        return $1.add($2);
+      }), o('Invocation Accessor', function() {
+        return new Value($1, [].concat($2));
+      }), o('ThisProperty')
+    ],
+    Assignable: [
+      o('SimpleAssignable'), o('Array', function() {
+        return new Value($1);
+      }), o('Object', function() {
+        return new Value($1);
+      })
+    ],
+    Value: [
+      o('Assignable'), o('Literal', function() {
+        return new Value($1);
+      }), o('Parenthetical', function() {
+        return new Value($1);
+      }), o('Range', function() {
+        return new Value($1);
+      }), o('This')
+    ],
+    Accessor: [
+      o('.  Identifier', function() {
+        return new Access($2);
+      }), o('?. Identifier', function() {
+        return new Access($2, 'soak');
+      }), o(':: Identifier', function() {
+        return [new Access(new Literal('prototype')), new Access($2)];
+      }), o('::', function() {
+        return new Access(new Literal('prototype'));
+      }), o('Index')
+    ],
+    Index: [
+      o('INDEX_START IndexValue INDEX_END', function() {
+        return $2;
+      }), o('INDEX_SOAK  Index', function() {
+        return extend($2, {
+          soak: true
+        });
+      })
+    ],
+    IndexValue: [
+      o('Expression', function() {
+        return new Index($1);
+      }), o('Slice', function() {
+        return new Slice($1);
+      })
+    ],
+    Object: [
+      o('{ AssignList OptComma }', function() {
+        return new Obj($2, $1.generated);
+      })
+    ],
+    AssignList: [
+      o('', function() {
+        return [];
+      }), o('AssignObj', function() {
+        return [$1];
+      }), o('AssignList , AssignObj', function() {
+        return $1.concat($3);
+      }), o('AssignList OptComma TERMINATOR AssignObj', function() {
+        return $1.concat($4);
+      }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
+        return $1.concat($4);
+      })
+    ],
+    Class: [
+      o('CLASS', function() {
+        return new Class;
+      }), o('CLASS Block', function() {
+        return new Class(null, null, $2);
+      }), o('CLASS EXTENDS Expression', function() {
+        return new Class(null, $3);
+      }), o('CLASS EXTENDS Expression Block', function() {
+        return new Class(null, $3, $4);
+      }), o('CLASS SimpleAssignable', function() {
+        return new Class($2);
+      }), o('CLASS SimpleAssignable Block', function() {
+        return new Class($2, null, $3);
+      }), o('CLASS SimpleAssignable EXTENDS Expression', function() {
+        return new Class($2, $4);
+      }), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
+        return new Class($2, $4, $5);
+      })
+    ],
+    Invocation: [
+      o('Value OptFuncExist Arguments', function() {
+        return new Call($1, $3, $2);
+      }), o('Invocation OptFuncExist Arguments', function() {
+        return new Call($1, $3, $2);
+      }), o('SUPER', function() {
+        return new Call('super', [new Splat(new Literal('arguments'))]);
+      }), o('SUPER Arguments', function() {
+        return new Call('super', $2);
+      })
+    ],
+    OptFuncExist: [
+      o('', function() {
+        return false;
+      }), o('FUNC_EXIST', function() {
+        return true;
+      })
+    ],
+    Arguments: [
+      o('CALL_START CALL_END', function() {
+        return [];
+      }), o('CALL_START ArgList OptComma CALL_END', function() {
+        return $2;
+      })
+    ],
+    This: [
+      o('THIS', function() {
+        return new Value(new Literal('this'));
+      }), o('@', function() {
+        return new Value(new Literal('this'));
+      })
+    ],
+    ThisProperty: [
+      o('@ Identifier', function() {
+        return new Value(new Literal('this'), [new Access($2)], 'this');
+      })
+    ],
+    Array: [
+      o('[ ]', function() {
+        return new Arr([]);
+      }), o('[ ArgList OptComma ]', function() {
+        return new Arr($2);
+      })
+    ],
+    RangeDots: [
+      o('..', function() {
+        return 'inclusive';
+      }), o('...', function() {
+        return 'exclusive';
+      })
+    ],
+    Range: [
+      o('[ Expression RangeDots Expression ]', function() {
+        return new Range($2, $4, $3);
+      })
+    ],
+    Slice: [
+      o('Expression RangeDots Expression', function() {
+        return new Range($1, $3, $2);
+      }), o('Expression RangeDots', function() {
+        return new Range($1, null, $2);
+      }), o('RangeDots Expression', function() {
+        return new Range(null, $2, $1);
+      })
+    ],
+    ArgList: [
+      o('Arg', function() {
+        return [$1];
+      }), o('ArgList , Arg', function() {
+        return $1.concat($3);
+      }), o('ArgList OptComma TERMINATOR Arg', function() {
+        return $1.concat($4);
+      }), o('INDENT ArgList OptComma OUTDENT', function() {
+        return $2;
+      }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
+        return $1.concat($4);
+      })
+    ],
+    Arg: [o('Expression'), o('Splat')],
+    SimpleArgs: [
+      o('Expression'), o('SimpleArgs , Expression', function() {
+        return [].concat($1, $3);
+      })
+    ],
+    Try: [
+      o('TRY Block', function() {
+        return new Try($2);
+      }), o('TRY Block Catch', function() {
+        return new Try($2, $3[0], $3[1]);
+      }), o('TRY Block FINALLY Block', function() {
+        return new Try($2, null, null, $4);
+      }), o('TRY Block Catch FINALLY Block', function() {
+        return new Try($2, $3[0], $3[1], $5);
+      })
+    ],
+    Catch: [
+      o('CATCH Identifier Block', function() {
+        return [$2, $3];
+      })
+    ],
+    Throw: [
+      o('THROW Expression', function() {
+        return new Throw($2);
+      })
+    ],
+    Parenthetical: [
+      o('( Body )', function() {
+        return new Parens($2);
+      }), o('( INDENT Body OUTDENT )', function() {
+        return new Parens($3);
+      })
+    ],
+    WhileSource: [
+      o('WHILE Expression', function() {
+        return new While($2);
+      }), o('WHILE Expression WHEN Expression', function() {
+        return new While($2, {
+          guard: $4
+        });
+      }), o('UNTIL Expression', function() {
+        return new While($2, {
+          invert: true
+        });
+      }), o('UNTIL Expression WHEN Expression', function() {
+        return new While($2, {
+          invert: true,
+          guard: $4
+        });
+      })
+    ],
+    While: [
+      o('WhileSource Block', function() {
+        return $1.addBody($2);
+      }), o('Statement  WhileSource', function() {
+        return $2.addBody(Block.wrap([$1]));
+      }), o('Expression WhileSource', function() {
+        return $2.addBody(Block.wrap([$1]));
+      }), o('Loop', function() {
+        return $1;
+      })
+    ],
+    Loop: [
+      o('LOOP Block', function() {
+        return new While(new Literal('true')).addBody($2);
+      }), o('LOOP Expression', function() {
+        return new While(new Literal('true')).addBody(Block.wrap([$2]));
+      })
+    ],
+    For: [
+      o('Statement  ForBody', function() {
+        return new For($1, $2);
+      }), o('Expression ForBody', function() {
+        return new For($1, $2);
+      }), o('ForBody    Block', function() {
+        return new For($2, $1);
+      })
+    ],
+    ForBody: [
+      o('FOR Range', function() {
+        return {
+          source: new Value($2)
+        };
+      }), o('ForStart ForSource', function() {
+        $2.own = $1.own;
+        $2.name = $1[0];
+        $2.index = $1[1];
+        return $2;
+      })
+    ],
+    ForStart: [
+      o('FOR ForVariables', function() {
+        return $2;
+      }), o('FOR OWN ForVariables', function() {
+        $3.own = true;
+        return $3;
+      })
+    ],
+    ForValue: [
+      o('Identifier'), o('Array', function() {
+        return new Value($1);
+      }), o('Object', function() {
+        return new Value($1);
+      })
+    ],
+    ForVariables: [
+      o('ForValue', function() {
+        return [$1];
+      }), o('ForValue , ForValue', function() {
+        return [$1, $3];
+      })
+    ],
+    ForSource: [
+      o('FORIN Expression', function() {
+        return {
+          source: $2
+        };
+      }), o('FOROF Expression', function() {
+        return {
+          source: $2,
+          object: true
+        };
+      }), o('FORIN Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          guard: $4
+        };
+      }), o('FOROF Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          guard: $4,
+          object: true
+        };
+      }), o('FORIN Expression BY Expression', function() {
+        return {
+          source: $2,
+          step: $4
+        };
+      }), o('FORIN Expression WHEN Expression BY Expression', function() {
+        return {
+          source: $2,
+          guard: $4,
+          step: $6
+        };
+      }), o('FORIN Expression BY Expression WHEN Expression', function() {
+        return {
+          source: $2,
+          step: $4,
+          guard: $6
+        };
+      })
+    ],
+    Switch: [
+      o('SWITCH Expression INDENT Whens OUTDENT', function() {
+        return new Switch($2, $4);
+      }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
+        return new Switch($2, $4, $6);
+      }), o('SWITCH INDENT Whens OUTDENT', function() {
+        return new Switch(null, $3);
+      }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
+        return new Switch(null, $3, $5);
+      })
+    ],
+    Whens: [
+      o('When'), o('Whens When', function() {
+        return $1.concat($2);
+      })
+    ],
+    When: [
+      o('LEADING_WHEN SimpleArgs Block', function() {
+        return [[$2, $3]];
+      }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
+        return [[$2, $3]];
+      })
+    ],
+    IfBlock: [
+      o('IF Expression Block', function() {
+        return new If($2, $3, {
+          type: $1
+        });
+      }), o('IfBlock ELSE IF Expression Block', function() {
+        return $1.addElse(new If($4, $5, {
+          type: $3
+        }));
+      })
+    ],
+    If: [
+      o('IfBlock'), o('IfBlock ELSE Block', function() {
+        return $1.addElse($3);
+      }), o('Statement  POST_IF Expression', function() {
+        return new If($3, Block.wrap([$1]), {
+          type: $2,
+          statement: true
+        });
+      }), o('Expression POST_IF Expression', function() {
+        return new If($3, Block.wrap([$1]), {
+          type: $2,
+          statement: true
+        });
+      })
+    ],
+    Operation: [
+      o('UNARY Expression', function() {
+        return new Op($1, $2);
+      }), o('-     Expression', (function() {
+        return new Op('-', $2);
+      }), {
+        prec: 'UNARY'
+      }), o('+     Expression', (function() {
+        return new Op('+', $2);
+      }), {
+        prec: 'UNARY'
+      }), o('-- SimpleAssignable', function() {
+        return new Op('--', $2);
+      }), o('++ SimpleAssignable', function() {
+        return new Op('++', $2);
+      }), o('SimpleAssignable --', function() {
+        return new Op('--', $1, null, true);
+      }), o('SimpleAssignable ++', function() {
+        return new Op('++', $1, null, true);
+      }), o('Expression ?', function() {
+        return new Existence($1);
+      }), o('Expression +  Expression', function() {
+        return new Op('+', $1, $3);
+      }), o('Expression -  Expression', function() {
+        return new Op('-', $1, $3);
+      }), o('Expression MATH     Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression SHIFT    Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression COMPARE  Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression LOGIC    Expression', function() {
+        return new Op($2, $1, $3);
+      }), o('Expression RELATION Expression', function() {
+        if ($2.charAt(0) === '!') {
+          return new Op($2.slice(1), $1, $3).invert();
+        } else {
+          return new Op($2, $1, $3);
+        }
+      }), o('SimpleAssignable COMPOUND_ASSIGN\
+       Expression', function() {
+        return new Assign($1, $3, $2);
+      }), o('SimpleAssignable COMPOUND_ASSIGN\
+       INDENT Expression OUTDENT', function() {
+        return new Assign($1, $4, $2);
+      }), o('SimpleAssignable EXTENDS Expression', function() {
+        return new Extends($1, $3);
+      })
+    ]
+  };
+
+  operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
+
+  tokens = [];
+
+  for (name in grammar) {
+    alternatives = grammar[name];
+    grammar[name] = (function() {
+      var _i, _j, _len, _len2, _ref, _results;
+      _results = [];
+      for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
+        alt = alternatives[_i];
+        _ref = alt[0].split(' ');
+        for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
+          token = _ref[_j];
+          if (!grammar[token]) tokens.push(token);
+        }
+        if (name === 'Root') alt[1] = "return " + alt[1];
+        _results.push(alt);
+      }
+      return _results;
+    })();
+  }
+
+  exports.parser = new Parser({
+    tokens: tokens.join(' '),
+    bnf: grammar,
+    operators: operators.reverse(),
+    startSymbol: 'Root'
+  });
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/helpers.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/helpers.js
new file mode 100644
index 0000000..038f781
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/helpers.js
@@ -0,0 +1,72 @@
+(function() {
+  var extend, flatten;
+
+  exports.starts = function(string, literal, start) {
+    return literal === string.substr(start, literal.length);
+  };
+
+  exports.ends = function(string, literal, back) {
+    var len;
+    len = literal.length;
+    return literal === string.substr(string.length - len - (back || 0), len);
+  };
+
+  exports.compact = function(array) {
+    var item, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = array.length; _i < _len; _i++) {
+      item = array[_i];
+      if (item) _results.push(item);
+    }
+    return _results;
+  };
+
+  exports.count = function(string, substr) {
+    var num, pos;
+    num = pos = 0;
+    if (!substr.length) return 1 / 0;
+    while (pos = 1 + string.indexOf(substr, pos)) {
+      num++;
+    }
+    return num;
+  };
+
+  exports.merge = function(options, overrides) {
+    return extend(extend({}, options), overrides);
+  };
+
+  extend = exports.extend = function(object, properties) {
+    var key, val;
+    for (key in properties) {
+      val = properties[key];
+      object[key] = val;
+    }
+    return object;
+  };
+
+  exports.flatten = flatten = function(array) {
+    var element, flattened, _i, _len;
+    flattened = [];
+    for (_i = 0, _len = array.length; _i < _len; _i++) {
+      element = array[_i];
+      if (element instanceof Array) {
+        flattened = flattened.concat(flatten(element));
+      } else {
+        flattened.push(element);
+      }
+    }
+    return flattened;
+  };
+
+  exports.del = function(obj, key) {
+    var val;
+    val = obj[key];
+    delete obj[key];
+    return val;
+  };
+
+  exports.last = function(array, back) {
+    return array[array.length - (back || 0) - 1];
+  };
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/index.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/index.js
new file mode 100644
index 0000000..5e6eba9
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/index.js
@@ -0,0 +1,10 @@
+(function() {
+  var key, val, _ref;
+
+  _ref = require('./coffee-script');
+  for (key in _ref) {
+    val = _ref[key];
+    exports[key] = val;
+  }
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/lexer.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/lexer.js
new file mode 100644
index 0000000..1dd3b04
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/lexer.js
@@ -0,0 +1,686 @@
+(function() {
+  var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref2,
+    __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
+
+  _ref2 = require('./helpers'), count = _ref2.count, starts = _ref2.starts, compact = _ref2.compact, last = _ref2.last;
+
+  exports.Lexer = Lexer = (function() {
+
+    function Lexer() {}
+
+    Lexer.prototype.tokenize = function(code, opts) {
+      var i, tag;
+      if (opts == null) opts = {};
+      if (WHITESPACE.test(code)) code = "\n" + code;
+      code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
+      this.code = code;
+      this.line = opts.line || 0;
+      this.indent = 0;
+      this.indebt = 0;
+      this.outdebt = 0;
+      this.indents = [];
+      this.ends = [];
+      this.tokens = [];
+      i = 0;
+      while (this.chunk = code.slice(i)) {
+        i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
+      }
+      this.closeIndentation();
+      if (tag = this.ends.pop()) this.error("missing " + tag);
+      if (opts.rewrite === false) return this.tokens;
+      return (new Rewriter).rewrite(this.tokens);
+    };
+
+    Lexer.prototype.identifierToken = function() {
+      var colon, forcedIdentifier, id, input, match, prev, tag, _ref3, _ref4;
+      if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
+      input = match[0], id = match[1], colon = match[2];
+      if (id === 'own' && this.tag() === 'FOR') {
+        this.token('OWN', id);
+        return id.length;
+      }
+      forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref3 = prev[0]) === '.' || _ref3 === '?.' || _ref3 === '::') || !prev.spaced && prev[0] === '@');
+      tag = 'IDENTIFIER';
+      if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
+        tag = id.toUpperCase();
+        if (tag === 'WHEN' && (_ref4 = this.tag(), __indexOf.call(LINE_BREAK, _ref4) >= 0)) {
+          tag = 'LEADING_WHEN';
+        } else if (tag === 'FOR') {
+          this.seenFor = true;
+        } else if (tag === 'UNLESS') {
+          tag = 'IF';
+        } else if (__indexOf.call(UNARY, tag) >= 0) {
+          tag = 'UNARY';
+        } else if (__indexOf.call(RELATION, tag) >= 0) {
+          if (tag !== 'INSTANCEOF' && this.seenFor) {
+            tag = 'FOR' + tag;
+            this.seenFor = false;
+          } else {
+            tag = 'RELATION';
+            if (this.value() === '!') {
+              this.tokens.pop();
+              id = '!' + id;
+            }
+          }
+        }
+      }
+      if (__indexOf.call(['eval', 'arguments'].concat(JS_FORBIDDEN), id) >= 0) {
+        if (forcedIdentifier) {
+          tag = 'IDENTIFIER';
+          id = new String(id);
+          id.reserved = true;
+        } else if (__indexOf.call(RESERVED, id) >= 0) {
+          this.error("reserved word \"" + id + "\"");
+        }
+      }
+      if (!forcedIdentifier) {
+        if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
+        tag = (function() {
+          switch (id) {
+            case '!':
+              return 'UNARY';
+            case '==':
+            case '!=':
+              return 'COMPARE';
+            case '&&':
+            case '||':
+              return 'LOGIC';
+            case 'true':
+            case 'false':
+            case 'null':
+            case 'undefined':
+              return 'BOOL';
+            case 'break':
+            case 'continue':
+              return 'STATEMENT';
+            default:
+              return tag;
+          }
+        })();
+      }
+      this.token(tag, id);
+      if (colon) this.token(':', ':');
+      return input.length;
+    };
+
+    Lexer.prototype.numberToken = function() {
+      var binaryLiteral, lexedLength, match, number;
+      if (!(match = NUMBER.exec(this.chunk))) return 0;
+      number = match[0];
+      lexedLength = number.length;
+      if (binaryLiteral = /0b([01]+)/.exec(number)) {
+        number = (parseInt(binaryLiteral[1], 2)).toString();
+      }
+      this.token('NUMBER', number);
+      return lexedLength;
+    };
+
+    Lexer.prototype.stringToken = function() {
+      var match, string;
+      switch (this.chunk.charAt(0)) {
+        case "'":
+          if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
+          this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
+          break;
+        case '"':
+          if (!(string = this.balancedString(this.chunk, '"'))) return 0;
+          if (0 < string.indexOf('#{', 1)) {
+            this.interpolateString(string.slice(1, -1));
+          } else {
+            this.token('STRING', this.escapeLines(string));
+          }
+          break;
+        default:
+          return 0;
+      }
+      this.line += count(string, '\n');
+      return string.length;
+    };
+
+    Lexer.prototype.heredocToken = function() {
+      var doc, heredoc, match, quote;
+      if (!(match = HEREDOC.exec(this.chunk))) return 0;
+      heredoc = match[0];
+      quote = heredoc.charAt(0);
+      doc = this.sanitizeHeredoc(match[2], {
+        quote: quote,
+        indent: null
+      });
+      if (quote === '"' && 0 <= doc.indexOf('#{')) {
+        this.interpolateString(doc, {
+          heredoc: true
+        });
+      } else {
+        this.token('STRING', this.makeString(doc, quote, true));
+      }
+      this.line += count(heredoc, '\n');
+      return heredoc.length;
+    };
+
+    Lexer.prototype.commentToken = function() {
+      var comment, here, match;
+      if (!(match = this.chunk.match(COMMENT))) return 0;
+      comment = match[0], here = match[1];
+      if (here) {
+        this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
+          herecomment: true,
+          indent: Array(this.indent + 1).join(' ')
+        }));
+        this.token('TERMINATOR', '\n');
+      }
+      this.line += count(comment, '\n');
+      return comment.length;
+    };
+
+    Lexer.prototype.jsToken = function() {
+      var match, script;
+      if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
+        return 0;
+      }
+      this.token('JS', (script = match[0]).slice(1, -1));
+      return script.length;
+    };
+
+    Lexer.prototype.regexToken = function() {
+      var flags, length, match, prev, regex, _ref3, _ref4;
+      if (this.chunk.charAt(0) !== '/') return 0;
+      if (match = HEREGEX.exec(this.chunk)) {
+        length = this.heregexToken(match);
+        this.line += count(match[0], '\n');
+        return length;
+      }
+      prev = last(this.tokens);
+      if (prev && (_ref3 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref3) >= 0)) {
+        return 0;
+      }
+      if (!(match = REGEX.exec(this.chunk))) return 0;
+      _ref4 = match, match = _ref4[0], regex = _ref4[1], flags = _ref4[2];
+      if (regex.slice(0, 2) === '/*') {
+        this.error('regular expressions cannot begin with `*`');
+      }
+      if (regex === '//') regex = '/(?:)/';
+      this.token('REGEX', "" + regex + flags);
+      return match.length;
+    };
+
+    Lexer.prototype.heregexToken = function(match) {
+      var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref3, _ref4, _ref5, _ref6;
+      heregex = match[0], body = match[1], flags = match[2];
+      if (0 > body.indexOf('#{')) {
+        re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
+        if (re.match(/^\*/)) {
+          this.error('regular expressions cannot begin with `*`');
+        }
+        this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
+        return heregex.length;
+      }
+      this.token('IDENTIFIER', 'RegExp');
+      this.tokens.push(['CALL_START', '(']);
+      tokens = [];
+      _ref3 = this.interpolateString(body, {
+        regex: true
+      });
+      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+        _ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[1];
+        if (tag === 'TOKENS') {
+          tokens.push.apply(tokens, value);
+        } else {
+          if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
+          value = value.replace(/\\/g, '\\\\');
+          tokens.push(['STRING', this.makeString(value, '"', true)]);
+        }
+        tokens.push(['+', '+']);
+      }
+      tokens.pop();
+      if (((_ref5 = tokens[0]) != null ? _ref5[0] : void 0) !== 'STRING') {
+        this.tokens.push(['STRING', '""'], ['+', '+']);
+      }
+      (_ref6 = this.tokens).push.apply(_ref6, tokens);
+      if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
+      this.token(')', ')');
+      return heregex.length;
+    };
+
+    Lexer.prototype.lineToken = function() {
+      var diff, indent, match, noNewlines, prev, size;
+      if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
+      indent = match[0];
+      this.line += count(indent, '\n');
+      this.seenFor = false;
+      prev = last(this.tokens, 1);
+      size = indent.length - 1 - indent.lastIndexOf('\n');
+      noNewlines = this.unfinished();
+      if (size - this.indebt === this.indent) {
+        if (noNewlines) {
+          this.suppressNewlines();
+        } else {
+          this.newlineToken();
+        }
+        return indent.length;
+      }
+      if (size > this.indent) {
+        if (noNewlines) {
+          this.indebt = size - this.indent;
+          this.suppressNewlines();
+          return indent.length;
+        }
+        diff = size - this.indent + this.outdebt;
+        this.token('INDENT', diff);
+        this.indents.push(diff);
+        this.ends.push('OUTDENT');
+        this.outdebt = this.indebt = 0;
+      } else {
+        this.indebt = 0;
+        this.outdentToken(this.indent - size, noNewlines);
+      }
+      this.indent = size;
+      return indent.length;
+    };
+
+    Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
+      var dent, len;
+      while (moveOut > 0) {
+        len = this.indents.length - 1;
+        if (this.indents[len] === void 0) {
+          moveOut = 0;
+        } else if (this.indents[len] === this.outdebt) {
+          moveOut -= this.outdebt;
+          this.outdebt = 0;
+        } else if (this.indents[len] < this.outdebt) {
+          this.outdebt -= this.indents[len];
+          moveOut -= this.indents[len];
+        } else {
+          dent = this.indents.pop() - this.outdebt;
+          moveOut -= dent;
+          this.outdebt = 0;
+          this.pair('OUTDENT');
+          this.token('OUTDENT', dent);
+        }
+      }
+      if (dent) this.outdebt -= moveOut;
+      while (this.value() === ';') {
+        this.tokens.pop();
+      }
+      if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
+        this.token('TERMINATOR', '\n');
+      }
+      return this;
+    };
+
+    Lexer.prototype.whitespaceToken = function() {
+      var match, nline, prev;
+      if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
+        return 0;
+      }
+      prev = last(this.tokens);
+      if (prev) prev[match ? 'spaced' : 'newLine'] = true;
+      if (match) {
+        return match[0].length;
+      } else {
+        return 0;
+      }
+    };
+
+    Lexer.prototype.newlineToken = function() {
+      while (this.value() === ';') {
+        this.tokens.pop();
+      }
+      if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
+      return this;
+    };
+
+    Lexer.prototype.suppressNewlines = function() {
+      if (this.value() === '\\') this.tokens.pop();
+      return this;
+    };
+
+    Lexer.prototype.literalToken = function() {
+      var match, prev, tag, value, _ref3, _ref4, _ref5, _ref6;
+      if (match = OPERATOR.exec(this.chunk)) {
+        value = match[0];
+        if (CODE.test(value)) this.tagParameters();
+      } else {
+        value = this.chunk.charAt(0);
+      }
+      tag = value;
+      prev = last(this.tokens);
+      if (value === '=' && prev) {
+        if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) {
+          this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
+        }
+        if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') {
+          prev[0] = 'COMPOUND_ASSIGN';
+          prev[1] += '=';
+          return value.length;
+        }
+      }
+      if (value === ';') {
+        this.seenFor = false;
+        tag = 'TERMINATOR';
+      } else if (__indexOf.call(MATH, value) >= 0) {
+        tag = 'MATH';
+      } else if (__indexOf.call(COMPARE, value) >= 0) {
+        tag = 'COMPARE';
+      } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {
+        tag = 'COMPOUND_ASSIGN';
+      } else if (__indexOf.call(UNARY, value) >= 0) {
+        tag = 'UNARY';
+      } else if (__indexOf.call(SHIFT, value) >= 0) {
+        tag = 'SHIFT';
+      } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
+        tag = 'LOGIC';
+      } else if (prev && !prev.spaced) {
+        if (value === '(' && (_ref5 = prev[0], __indexOf.call(CALLABLE, _ref5) >= 0)) {
+          if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
+          tag = 'CALL_START';
+        } else if (value === '[' && (_ref6 = prev[0], __indexOf.call(INDEXABLE, _ref6) >= 0)) {
+          tag = 'INDEX_START';
+          switch (prev[0]) {
+            case '?':
+              prev[0] = 'INDEX_SOAK';
+          }
+        }
+      }
+      switch (value) {
+        case '(':
+        case '{':
+        case '[':
+          this.ends.push(INVERSES[value]);
+          break;
+        case ')':
+        case '}':
+        case ']':
+          this.pair(value);
+      }
+      this.token(tag, value);
+      return value.length;
+    };
+
+    Lexer.prototype.sanitizeHeredoc = function(doc, options) {
+      var attempt, herecomment, indent, match, _ref3;
+      indent = options.indent, herecomment = options.herecomment;
+      if (herecomment) {
+        if (HEREDOC_ILLEGAL.test(doc)) {
+          this.error("block comment cannot contain \"*/\", starting");
+        }
+        if (doc.indexOf('\n') <= 0) return doc;
+      } else {
+        while (match = HEREDOC_INDENT.exec(doc)) {
+          attempt = match[1];
+          if (indent === null || (0 < (_ref3 = attempt.length) && _ref3 < indent.length)) {
+            indent = attempt;
+          }
+        }
+      }
+      if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
+      if (!herecomment) doc = doc.replace(/^\n/, '');
+      return doc;
+    };
+
+    Lexer.prototype.tagParameters = function() {
+      var i, stack, tok, tokens;
+      if (this.tag() !== ')') return this;
+      stack = [];
+      tokens = this.tokens;
+      i = tokens.length;
+      tokens[--i][0] = 'PARAM_END';
+      while (tok = tokens[--i]) {
+        switch (tok[0]) {
+          case ')':
+            stack.push(tok);
+            break;
+          case '(':
+          case 'CALL_START':
+            if (stack.length) {
+              stack.pop();
+            } else if (tok[0] === '(') {
+              tok[0] = 'PARAM_START';
+              return this;
+            } else {
+              return this;
+            }
+        }
+      }
+      return this;
+    };
+
+    Lexer.prototype.closeIndentation = function() {
+      return this.outdentToken(this.indent);
+    };
+
+    Lexer.prototype.balancedString = function(str, end) {
+      var i, letter, match, prev, stack, _ref3;
+      stack = [end];
+      for (i = 1, _ref3 = str.length; 1 <= _ref3 ? i < _ref3 : i > _ref3; 1 <= _ref3 ? i++ : i--) {
+        switch (letter = str.charAt(i)) {
+          case '\\':
+            i++;
+            continue;
+          case end:
+            stack.pop();
+            if (!stack.length) return str.slice(0, i + 1);
+            end = stack[stack.length - 1];
+            continue;
+        }
+        if (end === '}' && (letter === '"' || letter === "'")) {
+          stack.push(end = letter);
+        } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
+          i += match[0].length - 1;
+        } else if (end === '}' && letter === '{') {
+          stack.push(end = '}');
+        } else if (end === '"' && prev === '#' && letter === '{') {
+          stack.push(end = '}');
+        }
+        prev = letter;
+      }
+      return this.error("missing " + (stack.pop()) + ", starting");
+    };
+
+    Lexer.prototype.interpolateString = function(str, options) {
+      var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5;
+      if (options == null) options = {};
+      heredoc = options.heredoc, regex = options.regex;
+      tokens = [];
+      pi = 0;
+      i = -1;
+      while (letter = str.charAt(i += 1)) {
+        if (letter === '\\') {
+          i += 1;
+          continue;
+        }
+        if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
+          continue;
+        }
+        if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
+        inner = expr.slice(1, -1);
+        if (inner.length) {
+          nested = new Lexer().tokenize(inner, {
+            line: this.line,
+            rewrite: false
+          });
+          nested.pop();
+          if (((_ref3 = nested[0]) != null ? _ref3[0] : void 0) === 'TERMINATOR') {
+            nested.shift();
+          }
+          if (len = nested.length) {
+            if (len > 1) {
+              nested.unshift(['(', '(', this.line]);
+              nested.push([')', ')', this.line]);
+            }
+            tokens.push(['TOKENS', nested]);
+          }
+        }
+        i += expr.length;
+        pi = i + 1;
+      }
+      if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
+      if (regex) return tokens;
+      if (!tokens.length) return this.token('STRING', '""');
+      if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
+      if (interpolated = tokens.length > 1) this.token('(', '(');
+      for (i = 0, _len = tokens.length; i < _len; i++) {
+        _ref4 = tokens[i], tag = _ref4[0], value = _ref4[1];
+        if (i) this.token('+', '+');
+        if (tag === 'TOKENS') {
+          (_ref5 = this.tokens).push.apply(_ref5, value);
+        } else {
+          this.token('STRING', this.makeString(value, '"', heredoc));
+        }
+      }
+      if (interpolated) this.token(')', ')');
+      return tokens;
+    };
+
+    Lexer.prototype.pair = function(tag) {
+      var size, wanted;
+      if (tag !== (wanted = last(this.ends))) {
+        if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
+        this.indent -= size = last(this.indents);
+        this.outdentToken(size, true);
+        return this.pair(tag);
+      }
+      return this.ends.pop();
+    };
+
+    Lexer.prototype.token = function(tag, value) {
+      return this.tokens.push([tag, value, this.line]);
+    };
+
+    Lexer.prototype.tag = function(index, tag) {
+      var tok;
+      return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
+    };
+
+    Lexer.prototype.value = function(index, val) {
+      var tok;
+      return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
+    };
+
+    Lexer.prototype.unfinished = function() {
+      var _ref3;
+      return LINE_CONTINUER.test(this.chunk) || ((_ref3 = this.tag()) === '\\' || _ref3 === '.' || _ref3 === '?.' || _ref3 === 'UNARY' || _ref3 === 'MATH' || _ref3 === '+' || _ref3 === '-' || _ref3 === 'SHIFT' || _ref3 === 'RELATION' || _ref3 === 'COMPARE' || _ref3 === 'LOGIC' || _ref3 === 'COMPOUND_ASSIGN' || _ref3 === 'THROW' || _ref3 === 'EXTENDS');
+    };
+
+    Lexer.prototype.escapeLines = function(str, heredoc) {
+      return str.replace(MULTILINER, heredoc ? '\\n' : '');
+    };
+
+    Lexer.prototype.makeString = function(body, quote, heredoc) {
+      if (!body) return quote + quote;
+      body = body.replace(/\\([\s\S])/g, function(match, contents) {
+        if (contents === '\n' || contents === quote) {
+          return contents;
+        } else {
+          return match;
+        }
+      });
+      body = body.replace(RegExp("" + quote, "g"), '\\$&');
+      return quote + this.escapeLines(body, heredoc) + quote;
+    };
+
+    Lexer.prototype.error = function(message) {
+      throw SyntaxError("" + message + " on line " + (this.line + 1));
+    };
+
+    return Lexer;
+
+  })();
+
+  JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
+
+  COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
+
+  COFFEE_ALIAS_MAP = {
+    and: '&&',
+    or: '||',
+    is: '==',
+    isnt: '!=',
+    not: '!',
+    yes: 'true',
+    no: 'false',
+    on: 'true',
+    off: 'false'
+  };
+
+  COFFEE_ALIASES = (function() {
+    var _results;
+    _results = [];
+    for (key in COFFEE_ALIAS_MAP) {
+      _results.push(key);
+    }
+    return _results;
+  })();
+
+  COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
+
+  RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
+
+  JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
+
+  exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
+
+  IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
+
+  NUMBER = /^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
+
+  HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
+
+  OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
+
+  WHITESPACE = /^[^\n\S]+/;
+
+  COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
+
+  CODE = /^[-=]>/;
+
+  MULTI_DENT = /^(?:\n[^\n\S]*)+/;
+
+  SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
+
+  JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
+
+  REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/;
+
+  HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
+
+  HEREGEX_OMIT = /\s+(?:#.*)?/g;
+
+  MULTILINER = /\n/g;
+
+  HEREDOC_INDENT = /\n+([^\n\S]*)/g;
+
+  HEREDOC_ILLEGAL = /\*\//;
+
+  LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
+
+  TRAILING_SPACES = /\s+$/;
+
+  COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
+
+  UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
+
+  LOGIC = ['&&', '||', '&', '|', '^'];
+
+  SHIFT = ['<<', '>>', '>>>'];
+
+  COMPARE = ['==', '!=', '<', '>', '<=', '>='];
+
+  MATH = ['*', '/', '%'];
+
+  RELATION = ['IN', 'OF', 'INSTANCEOF'];
+
+  BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
+
+  NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
+
+  NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
+
+  CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
+
+  INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
+
+  LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/nodes.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/nodes.js
new file mode 100644
index 0000000..1941298
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/nodes.js
@@ -0,0 +1,2514 @@
+(function() {
+  var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref,
+    __hasProp = Object.prototype.hasOwnProperty,
+    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
+    __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  Scope = require('./scope').Scope;
+
+  RESERVED = require('./lexer').RESERVED;
+
+  _ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
+
+  exports.extend = extend;
+
+  YES = function() {
+    return true;
+  };
+
+  NO = function() {
+    return false;
+  };
+
+  THIS = function() {
+    return this;
+  };
+
+  NEGATE = function() {
+    this.negated = !this.negated;
+    return this;
+  };
+
+  exports.Base = Base = (function() {
+
+    function Base() {}
+
+    Base.prototype.compile = function(o, lvl) {
+      var node;
+      o = extend({}, o);
+      if (lvl) o.level = lvl;
+      node = this.unfoldSoak(o) || this;
+      node.tab = o.indent;
+      if (o.level === LEVEL_TOP || !node.isStatement(o)) {
+        return node.compileNode(o);
+      } else {
+        return node.compileClosure(o);
+      }
+    };
+
+    Base.prototype.compileClosure = function(o) {
+      if (this.jumps()) {
+        throw SyntaxError('cannot use a pure statement in an expression.');
+      }
+      o.sharedScope = true;
+      return Closure.wrap(this).compileNode(o);
+    };
+
+    Base.prototype.cache = function(o, level, reused) {
+      var ref, sub;
+      if (!this.isComplex()) {
+        ref = level ? this.compile(o, level) : this;
+        return [ref, ref];
+      } else {
+        ref = new Literal(reused || o.scope.freeVariable('ref'));
+        sub = new Assign(ref, this);
+        if (level) {
+          return [sub.compile(o, level), ref.value];
+        } else {
+          return [sub, ref];
+        }
+      }
+    };
+
+    Base.prototype.compileLoopReference = function(o, name) {
+      var src, tmp;
+      src = tmp = this.compile(o, LEVEL_LIST);
+      if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) {
+        src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src;
+      }
+      return [src, tmp];
+    };
+
+    Base.prototype.makeReturn = function(res) {
+      var me;
+      me = this.unwrapAll();
+      if (res) {
+        return new Call(new Literal("" + res + ".push"), [me]);
+      } else {
+        return new Return(me);
+      }
+    };
+
+    Base.prototype.contains = function(pred) {
+      var contains;
+      contains = false;
+      this.traverseChildren(false, function(node) {
+        if (pred(node)) {
+          contains = true;
+          return false;
+        }
+      });
+      return contains;
+    };
+
+    Base.prototype.containsType = function(type) {
+      return this instanceof type || this.contains(function(node) {
+        return node instanceof type;
+      });
+    };
+
+    Base.prototype.lastNonComment = function(list) {
+      var i;
+      i = list.length;
+      while (i--) {
+        if (!(list[i] instanceof Comment)) return list[i];
+      }
+      return null;
+    };
+
+    Base.prototype.toString = function(idt, name) {
+      var tree;
+      if (idt == null) idt = '';
+      if (name == null) name = this.constructor.name;
+      tree = '\n' + idt + name;
+      if (this.soak) tree += '?';
+      this.eachChild(function(node) {
+        return tree += node.toString(idt + TAB);
+      });
+      return tree;
+    };
+
+    Base.prototype.eachChild = function(func) {
+      var attr, child, _i, _j, _len, _len2, _ref2, _ref3;
+      if (!this.children) return this;
+      _ref2 = this.children;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        attr = _ref2[_i];
+        if (this[attr]) {
+          _ref3 = flatten([this[attr]]);
+          for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
+            child = _ref3[_j];
+            if (func(child) === false) return this;
+          }
+        }
+      }
+      return this;
+    };
+
+    Base.prototype.traverseChildren = function(crossScope, func) {
+      return this.eachChild(function(child) {
+        if (func(child) === false) return false;
+        return child.traverseChildren(crossScope, func);
+      });
+    };
+
+    Base.prototype.invert = function() {
+      return new Op('!', this);
+    };
+
+    Base.prototype.unwrapAll = function() {
+      var node;
+      node = this;
+      while (node !== (node = node.unwrap())) {
+        continue;
+      }
+      return node;
+    };
+
+    Base.prototype.children = [];
+
+    Base.prototype.isStatement = NO;
+
+    Base.prototype.jumps = NO;
+
+    Base.prototype.isComplex = YES;
+
+    Base.prototype.isChainable = NO;
+
+    Base.prototype.isAssignable = NO;
+
+    Base.prototype.unwrap = THIS;
+
+    Base.prototype.unfoldSoak = NO;
+
+    Base.prototype.assigns = NO;
+
+    return Base;
+
+  })();
+
+  exports.Block = Block = (function(_super) {
+
+    __extends(Block, _super);
+
+    function Block(nodes) {
+      this.expressions = compact(flatten(nodes || []));
+    }
+
+    Block.prototype.children = ['expressions'];
+
+    Block.prototype.push = function(node) {
+      this.expressions.push(node);
+      return this;
+    };
+
+    Block.prototype.pop = function() {
+      return this.expressions.pop();
+    };
+
+    Block.prototype.unshift = function(node) {
+      this.expressions.unshift(node);
+      return this;
+    };
+
+    Block.prototype.unwrap = function() {
+      if (this.expressions.length === 1) {
+        return this.expressions[0];
+      } else {
+        return this;
+      }
+    };
+
+    Block.prototype.isEmpty = function() {
+      return !this.expressions.length;
+    };
+
+    Block.prototype.isStatement = function(o) {
+      var exp, _i, _len, _ref2;
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        exp = _ref2[_i];
+        if (exp.isStatement(o)) return true;
+      }
+      return false;
+    };
+
+    Block.prototype.jumps = function(o) {
+      var exp, _i, _len, _ref2;
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        exp = _ref2[_i];
+        if (exp.jumps(o)) return exp;
+      }
+    };
+
+    Block.prototype.makeReturn = function(res) {
+      var expr, len;
+      len = this.expressions.length;
+      while (len--) {
+        expr = this.expressions[len];
+        if (!(expr instanceof Comment)) {
+          this.expressions[len] = expr.makeReturn(res);
+          if (expr instanceof Return && !expr.expression) {
+            this.expressions.splice(len, 1);
+          }
+          break;
+        }
+      }
+      return this;
+    };
+
+    Block.prototype.compile = function(o, level) {
+      if (o == null) o = {};
+      if (o.scope) {
+        return Block.__super__.compile.call(this, o, level);
+      } else {
+        return this.compileRoot(o);
+      }
+    };
+
+    Block.prototype.compileNode = function(o) {
+      var code, codes, node, top, _i, _len, _ref2;
+      this.tab = o.indent;
+      top = o.level === LEVEL_TOP;
+      codes = [];
+      _ref2 = this.expressions;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        node = _ref2[_i];
+        node = node.unwrapAll();
+        node = node.unfoldSoak(o) || node;
+        if (node instanceof Block) {
+          codes.push(node.compileNode(o));
+        } else if (top) {
+          node.front = true;
+          code = node.compile(o);
+          codes.push(node.isStatement(o) ? code : "" + this.tab + code + ";");
+        } else {
+          codes.push(node.compile(o, LEVEL_LIST));
+        }
+      }
+      if (top) {
+        if (this.spaced) {
+          return "\n" + (codes.join('\n\n')) + "\n";
+        } else {
+          return codes.join('\n');
+        }
+      }
+      code = codes.join(', ') || 'void 0';
+      if (codes.length > 1 && o.level >= LEVEL_LIST) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+
+    Block.prototype.compileRoot = function(o) {
+      var code, exp, i, prelude, preludeExps, rest;
+      o.indent = o.bare ? '' : TAB;
+      o.scope = new Scope(null, this, null);
+      o.level = LEVEL_TOP;
+      this.spaced = true;
+      prelude = "";
+      if (!o.bare) {
+        preludeExps = (function() {
+          var _len, _ref2, _results;
+          _ref2 = this.expressions;
+          _results = [];
+          for (i = 0, _len = _ref2.length; i < _len; i++) {
+            exp = _ref2[i];
+            if (!(exp.unwrap() instanceof Comment)) break;
+            _results.push(exp);
+          }
+          return _results;
+        }).call(this);
+        rest = this.expressions.slice(preludeExps.length);
+        this.expressions = preludeExps;
+        if (preludeExps.length) {
+          prelude = "" + (this.compileNode(merge(o, {
+            indent: ''
+          }))) + "\n";
+        }
+        this.expressions = rest;
+      }
+      code = this.compileWithDeclarations(o);
+      if (o.bare) return code;
+      return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n";
+    };
+
+    Block.prototype.compileWithDeclarations = function(o) {
+      var assigns, code, declars, exp, i, post, rest, scope, spaced, _len, _ref2, _ref3, _ref4;
+      code = post = '';
+      _ref2 = this.expressions;
+      for (i = 0, _len = _ref2.length; i < _len; i++) {
+        exp = _ref2[i];
+        exp = exp.unwrap();
+        if (!(exp instanceof Comment || exp instanceof Literal)) break;
+      }
+      o = merge(o, {
+        level: LEVEL_TOP
+      });
+      if (i) {
+        rest = this.expressions.splice(i, 9e9);
+        _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1];
+        _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1];
+        this.expressions = rest;
+      }
+      post = this.compileNode(o);
+      scope = o.scope;
+      if (scope.expressions === this) {
+        declars = o.scope.hasDeclarations();
+        assigns = scope.hasAssignments;
+        if (declars || assigns) {
+          if (i) code += '\n';
+          code += "" + this.tab + "var ";
+          if (declars) code += scope.declaredVariables().join(', ');
+          if (assigns) {
+            if (declars) code += ",\n" + (this.tab + TAB);
+            code += scope.assignedVariables().join(",\n" + (this.tab + TAB));
+          }
+          code += ';\n';
+        }
+      }
+      return code + post;
+    };
+
+    Block.wrap = function(nodes) {
+      if (nodes.length === 1 && nodes[0] instanceof Block) return nodes[0];
+      return new Block(nodes);
+    };
+
+    return Block;
+
+  })(Base);
+
+  exports.Literal = Literal = (function(_super) {
+
+    __extends(Literal, _super);
+
+    function Literal(value) {
+      this.value = value;
+    }
+
+    Literal.prototype.makeReturn = function() {
+      if (this.isStatement()) {
+        return this;
+      } else {
+        return Literal.__super__.makeReturn.apply(this, arguments);
+      }
+    };
+
+    Literal.prototype.isAssignable = function() {
+      return IDENTIFIER.test(this.value);
+    };
+
+    Literal.prototype.isStatement = function() {
+      var _ref2;
+      return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';
+    };
+
+    Literal.prototype.isComplex = NO;
+
+    Literal.prototype.assigns = function(name) {
+      return name === this.value;
+    };
+
+    Literal.prototype.jumps = function(o) {
+      if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) {
+        return this;
+      }
+      if (this.value === 'continue' && !(o != null ? o.loop : void 0)) return this;
+    };
+
+    Literal.prototype.compileNode = function(o) {
+      var code, _ref2, _ref3;
+      code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved && ((_ref3 = "" + this.value) !== 'eval' && _ref3 !== 'arguments') ? "\"" + this.value + "\"" : this.value;
+      if (this.isStatement()) {
+        return "" + this.tab + code + ";";
+      } else {
+        return code;
+      }
+    };
+
+    Literal.prototype.toString = function() {
+      return ' "' + this.value + '"';
+    };
+
+    return Literal;
+
+  })(Base);
+
+  exports.Return = Return = (function(_super) {
+
+    __extends(Return, _super);
+
+    function Return(expr) {
+      if (expr && !expr.unwrap().isUndefined) this.expression = expr;
+    }
+
+    Return.prototype.children = ['expression'];
+
+    Return.prototype.isStatement = YES;
+
+    Return.prototype.makeReturn = THIS;
+
+    Return.prototype.jumps = THIS;
+
+    Return.prototype.compile = function(o, level) {
+      var expr, _ref2;
+      expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0;
+      if (expr && !(expr instanceof Return)) {
+        return expr.compile(o, level);
+      } else {
+        return Return.__super__.compile.call(this, o, level);
+      }
+    };
+
+    Return.prototype.compileNode = function(o) {
+      return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";");
+    };
+
+    return Return;
+
+  })(Base);
+
+  exports.Value = Value = (function(_super) {
+
+    __extends(Value, _super);
+
+    function Value(base, props, tag) {
+      if (!props && base instanceof Value) return base;
+      this.base = base;
+      this.properties = props || [];
+      if (tag) this[tag] = true;
+      return this;
+    }
+
+    Value.prototype.children = ['base', 'properties'];
+
+    Value.prototype.add = function(props) {
+      this.properties = this.properties.concat(props);
+      return this;
+    };
+
+    Value.prototype.hasProperties = function() {
+      return !!this.properties.length;
+    };
+
+    Value.prototype.isArray = function() {
+      return !this.properties.length && this.base instanceof Arr;
+    };
+
+    Value.prototype.isComplex = function() {
+      return this.hasProperties() || this.base.isComplex();
+    };
+
+    Value.prototype.isAssignable = function() {
+      return this.hasProperties() || this.base.isAssignable();
+    };
+
+    Value.prototype.isSimpleNumber = function() {
+      return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
+    };
+
+    Value.prototype.isAtomic = function() {
+      var node, _i, _len, _ref2;
+      _ref2 = this.properties.concat(this.base);
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        node = _ref2[_i];
+        if (node.soak || node instanceof Call) return false;
+      }
+      return true;
+    };
+
+    Value.prototype.isStatement = function(o) {
+      return !this.properties.length && this.base.isStatement(o);
+    };
+
+    Value.prototype.assigns = function(name) {
+      return !this.properties.length && this.base.assigns(name);
+    };
+
+    Value.prototype.jumps = function(o) {
+      return !this.properties.length && this.base.jumps(o);
+    };
+
+    Value.prototype.isObject = function(onlyGenerated) {
+      if (this.properties.length) return false;
+      return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated);
+    };
+
+    Value.prototype.isSplice = function() {
+      return last(this.properties) instanceof Slice;
+    };
+
+    Value.prototype.unwrap = function() {
+      if (this.properties.length) {
+        return this;
+      } else {
+        return this.base;
+      }
+    };
+
+    Value.prototype.cacheReference = function(o) {
+      var base, bref, name, nref;
+      name = last(this.properties);
+      if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) {
+        return [this, this];
+      }
+      base = new Value(this.base, this.properties.slice(0, -1));
+      if (base.isComplex()) {
+        bref = new Literal(o.scope.freeVariable('base'));
+        base = new Value(new Parens(new Assign(bref, base)));
+      }
+      if (!name) return [base, bref];
+      if (name.isComplex()) {
+        nref = new Literal(o.scope.freeVariable('name'));
+        name = new Index(new Assign(nref, name.index));
+        nref = new Index(nref);
+      }
+      return [base.add(name), new Value(bref || base.base, [nref || name])];
+    };
+
+    Value.prototype.compileNode = function(o) {
+      var code, prop, props, _i, _len;
+      this.base.front = this.front;
+      props = this.properties;
+      code = this.base.compile(o, props.length ? LEVEL_ACCESS : null);
+      if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) {
+        code = "" + code + ".";
+      }
+      for (_i = 0, _len = props.length; _i < _len; _i++) {
+        prop = props[_i];
+        code += prop.compile(o);
+      }
+      return code;
+    };
+
+    Value.prototype.unfoldSoak = function(o) {
+      var result,
+        _this = this;
+      if (this.unfoldedSoak != null) return this.unfoldedSoak;
+      result = (function() {
+        var fst, i, ifn, prop, ref, snd, _len, _ref2;
+        if (ifn = _this.base.unfoldSoak(o)) {
+          Array.prototype.push.apply(ifn.body.properties, _this.properties);
+          return ifn;
+        }
+        _ref2 = _this.properties;
+        for (i = 0, _len = _ref2.length; i < _len; i++) {
+          prop = _ref2[i];
+          if (!prop.soak) continue;
+          prop.soak = false;
+          fst = new Value(_this.base, _this.properties.slice(0, i));
+          snd = new Value(_this.base, _this.properties.slice(i));
+          if (fst.isComplex()) {
+            ref = new Literal(o.scope.freeVariable('ref'));
+            fst = new Parens(new Assign(ref, fst));
+            snd.base = ref;
+          }
+          return new If(new Existence(fst), snd, {
+            soak: true
+          });
+        }
+        return null;
+      })();
+      return this.unfoldedSoak = result || false;
+    };
+
+    return Value;
+
+  })(Base);
+
+  exports.Comment = Comment = (function(_super) {
+
+    __extends(Comment, _super);
+
+    function Comment(comment) {
+      this.comment = comment;
+    }
+
+    Comment.prototype.isStatement = YES;
+
+    Comment.prototype.makeReturn = THIS;
+
+    Comment.prototype.compileNode = function(o, level) {
+      var code;
+      code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/");
+      if ((level || o.level) === LEVEL_TOP) code = o.indent + code;
+      return code;
+    };
+
+    return Comment;
+
+  })(Base);
+
+  exports.Call = Call = (function(_super) {
+
+    __extends(Call, _super);
+
+    function Call(variable, args, soak) {
+      this.args = args != null ? args : [];
+      this.soak = soak;
+      this.isNew = false;
+      this.isSuper = variable === 'super';
+      this.variable = this.isSuper ? null : variable;
+    }
+
+    Call.prototype.children = ['variable', 'args'];
+
+    Call.prototype.newInstance = function() {
+      var base, _ref2;
+      base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable;
+      if (base instanceof Call && !base.isNew) {
+        base.newInstance();
+      } else {
+        this.isNew = true;
+      }
+      return this;
+    };
+
+    Call.prototype.superReference = function(o) {
+      var accesses, method, name;
+      method = o.scope.method;
+      if (!method) throw SyntaxError('cannot call super outside of a function.');
+      name = method.name;
+      if (name == null) {
+        throw SyntaxError('cannot call super on an anonymous function.');
+      }
+      if (method.klass) {
+        accesses = [new Access(new Literal('__super__'))];
+        if (method.static) accesses.push(new Access(new Literal('constructor')));
+        accesses.push(new Access(new Literal(name)));
+        return (new Value(new Literal(method.klass), accesses)).compile(o);
+      } else {
+        return "" + name + ".__super__.constructor";
+      }
+    };
+
+    Call.prototype.unfoldSoak = function(o) {
+      var call, ifn, left, list, rite, _i, _len, _ref2, _ref3;
+      if (this.soak) {
+        if (this.variable) {
+          if (ifn = unfoldSoak(o, this, 'variable')) return ifn;
+          _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1];
+        } else {
+          left = new Literal(this.superReference(o));
+          rite = new Value(left);
+        }
+        rite = new Call(rite, this.args);
+        rite.isNew = this.isNew;
+        left = new Literal("typeof " + (left.compile(o)) + " === \"function\"");
+        return new If(left, new Value(rite), {
+          soak: true
+        });
+      }
+      call = this;
+      list = [];
+      while (true) {
+        if (call.variable instanceof Call) {
+          list.push(call);
+          call = call.variable;
+          continue;
+        }
+        if (!(call.variable instanceof Value)) break;
+        list.push(call);
+        if (!((call = call.variable.base) instanceof Call)) break;
+      }
+      _ref3 = list.reverse();
+      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
+        call = _ref3[_i];
+        if (ifn) {
+          if (call.variable instanceof Call) {
+            call.variable = ifn;
+          } else {
+            call.variable.base = ifn;
+          }
+        }
+        ifn = unfoldSoak(o, call, 'variable');
+      }
+      return ifn;
+    };
+
+    Call.prototype.filterImplicitObjects = function(list) {
+      var node, nodes, obj, prop, properties, _i, _j, _len, _len2, _ref2;
+      nodes = [];
+      for (_i = 0, _len = list.length; _i < _len; _i++) {
+        node = list[_i];
+        if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) {
+          nodes.push(node);
+          continue;
+        }
+        obj = null;
+        _ref2 = node.base.properties;
+        for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
+          prop = _ref2[_j];
+          if (prop instanceof Assign || prop instanceof Comment) {
+            if (!obj) nodes.push(obj = new Obj(properties = [], true));
+            properties.push(prop);
+          } else {
+            nodes.push(prop);
+            obj = null;
+          }
+        }
+      }
+      return nodes;
+    };
+
+    Call.prototype.compileNode = function(o) {
+      var arg, args, code, _ref2;
+      if ((_ref2 = this.variable) != null) _ref2.front = this.front;
+      if (code = Splat.compileSplattedArray(o, this.args, true)) {
+        return this.compileSplat(o, code);
+      }
+      args = this.filterImplicitObjects(this.args);
+      args = ((function() {
+        var _i, _len, _results;
+        _results = [];
+        for (_i = 0, _len = args.length; _i < _len; _i++) {
+          arg = args[_i];
+          _results.push(arg.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })()).join(', ');
+      if (this.isSuper) {
+        return this.superReference(o) + (".call(this" + (args && ', ' + args) + ")");
+      } else {
+        return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")");
+      }
+    };
+
+    Call.prototype.compileSuper = function(args, o) {
+      return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")";
+    };
+
+    Call.prototype.compileSplat = function(o, splatArgs) {
+      var base, fun, idt, name, ref;
+      if (this.isSuper) {
+        return "" + (this.superReference(o)) + ".apply(this, " + splatArgs + ")";
+      }
+      if (this.isNew) {
+        idt = this.tab + TAB;
+        return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function() {})";
+      }
+      base = new Value(this.variable);
+      if ((name = base.properties.pop()) && base.isComplex()) {
+        ref = o.scope.freeVariable('ref');
+        fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
+      } else {
+        fun = base.compile(o, LEVEL_ACCESS);
+        if (SIMPLENUM.test(fun)) fun = "(" + fun + ")";
+        if (name) {
+          ref = fun;
+          fun += name.compile(o);
+        } else {
+          ref = 'null';
+        }
+      }
+      return "" + fun + ".apply(" + ref + ", " + splatArgs + ")";
+    };
+
+    return Call;
+
+  })(Base);
+
+  exports.Extends = Extends = (function(_super) {
+
+    __extends(Extends, _super);
+
+    function Extends(child, parent) {
+      this.child = child;
+      this.parent = parent;
+    }
+
+    Extends.prototype.children = ['child', 'parent'];
+
+    Extends.prototype.compile = function(o) {
+      return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
+    };
+
+    return Extends;
+
+  })(Base);
+
+  exports.Access = Access = (function(_super) {
+
+    __extends(Access, _super);
+
+    function Access(name, tag) {
+      this.name = name;
+      this.name.asKey = true;
+      this.soak = tag === 'soak';
+    }
+
+    Access.prototype.children = ['name'];
+
+    Access.prototype.compile = function(o) {
+      var name;
+      name = this.name.compile(o);
+      if (IDENTIFIER.test(name)) {
+        return "." + name;
+      } else {
+        return "[" + name + "]";
+      }
+    };
+
+    Access.prototype.isComplex = NO;
+
+    return Access;
+
+  })(Base);
+
+  exports.Index = Index = (function(_super) {
+
+    __extends(Index, _super);
+
+    function Index(index) {
+      this.index = index;
+    }
+
+    Index.prototype.children = ['index'];
+
+    Index.prototype.compile = function(o) {
+      return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]";
+    };
+
+    Index.prototype.isComplex = function() {
+      return this.index.isComplex();
+    };
+
+    return Index;
+
+  })(Base);
+
+  exports.Range = Range = (function(_super) {
+
+    __extends(Range, _super);
+
+    Range.prototype.children = ['from', 'to'];
+
+    function Range(from, to, tag) {
+      this.from = from;
+      this.to = to;
+      this.exclusive = tag === 'exclusive';
+      this.equals = this.exclusive ? '' : '=';
+    }
+
+    Range.prototype.compileVariables = function(o) {
+      var step, _ref2, _ref3, _ref4, _ref5;
+      o = merge(o, {
+        top: true
+      });
+      _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1];
+      _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1];
+      if (step = del(o, 'step')) {
+        _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1];
+      }
+      _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1];
+      if (this.stepVar) return this.stepNum = this.stepVar.match(SIMPLENUM);
+    };
+
+    Range.prototype.compileNode = function(o) {
+      var cond, condPart, from, gt, idx, known, lt, stepPart, to, varPart, _ref2, _ref3;
+      if (!this.fromVar) this.compileVariables(o);
+      if (!o.index) return this.compileArray(o);
+      known = this.fromNum && this.toNum;
+      idx = del(o, 'index');
+      varPart = "" + idx + " = " + this.fromC;
+      if (this.toC !== this.toVar) varPart += ", " + this.toC;
+      if (this.step !== this.stepVar) varPart += ", " + this.step;
+      _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1];
+      condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar);
+      stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? from <= to ? "" + idx + "++" : "" + idx + "--" : "" + cond + " ? " + idx + "++ : " + idx + "--";
+      return "" + varPart + "; " + condPart + "; " + stepPart;
+    };
+
+    Range.prototype.compileArray = function(o) {
+      var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results;
+      if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) {
+        range = (function() {
+          _results = [];
+          for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); }
+          return _results;
+        }).apply(this);
+        if (this.exclusive) range.pop();
+        return "[" + (range.join(', ')) + "]";
+      }
+      idt = this.tab + TAB;
+      i = o.scope.freeVariable('i');
+      result = o.scope.freeVariable('results');
+      pre = "\n" + idt + result + " = [];";
+      if (this.fromNum && this.toNum) {
+        o.index = i;
+        body = this.compileNode(o);
+      } else {
+        vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : '');
+        cond = "" + this.fromVar + " <= " + this.toVar;
+        body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--";
+      }
+      post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent;
+      hasArgs = function(node) {
+        return node != null ? node.contains(function(n) {
+          return n instanceof Literal && n.value === 'arguments' && !n.asKey;
+        }) : void 0;
+      };
+      if (hasArgs(this.from) || hasArgs(this.to)) args = ', arguments';
+      return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")";
+    };
+
+    return Range;
+
+  })(Base);
+
+  exports.Slice = Slice = (function(_super) {
+
+    __extends(Slice, _super);
+
+    Slice.prototype.children = ['range'];
+
+    function Slice(range) {
+      this.range = range;
+      Slice.__super__.constructor.call(this);
+    }
+
+    Slice.prototype.compileNode = function(o) {
+      var compiled, from, fromStr, to, toStr, _ref2;
+      _ref2 = this.range, to = _ref2.to, from = _ref2.from;
+      fromStr = from && from.compile(o, LEVEL_PAREN) || '0';
+      compiled = to && to.compile(o, LEVEL_ACCESS);
+      if (to && !(!this.range.exclusive && +compiled === -1)) {
+        toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? (+compiled + 1).toString() : "" + compiled + " + 1 || 9e9");
+      }
+      return ".slice(" + fromStr + (toStr || '') + ")";
+    };
+
+    return Slice;
+
+  })(Base);
+
+  exports.Obj = Obj = (function(_super) {
+
+    __extends(Obj, _super);
+
+    function Obj(props, generated) {
+      this.generated = generated != null ? generated : false;
+      this.objects = this.properties = props || [];
+    }
+
+    Obj.prototype.children = ['properties'];
+
+    Obj.prototype.compileNode = function(o) {
+      var i, idt, indent, join, lastNoncom, node, obj, prop, props, _i, _len;
+      props = this.properties;
+      if (!props.length) return (this.front ? '({})' : '{}');
+      if (this.generated) {
+        for (_i = 0, _len = props.length; _i < _len; _i++) {
+          node = props[_i];
+          if (node instanceof Value) {
+            throw new Error('cannot have an implicit value in an implicit object');
+          }
+        }
+      }
+      idt = o.indent += TAB;
+      lastNoncom = this.lastNonComment(this.properties);
+      props = (function() {
+        var _len2, _results;
+        _results = [];
+        for (i = 0, _len2 = props.length; i < _len2; i++) {
+          prop = props[i];
+          join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
+          indent = prop instanceof Comment ? '' : idt;
+          if (prop instanceof Value && prop["this"]) {
+            prop = new Assign(prop.properties[0].name, prop, 'object');
+          }
+          if (!(prop instanceof Comment)) {
+            if (!(prop instanceof Assign)) prop = new Assign(prop, prop, 'object');
+            (prop.variable.base || prop.variable).asKey = true;
+          }
+          _results.push(indent + prop.compile(o, LEVEL_TOP) + join);
+        }
+        return _results;
+      })();
+      props = props.join('');
+      obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}";
+      if (this.front) {
+        return "(" + obj + ")";
+      } else {
+        return obj;
+      }
+    };
+
+    Obj.prototype.assigns = function(name) {
+      var prop, _i, _len, _ref2;
+      _ref2 = this.properties;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        prop = _ref2[_i];
+        if (prop.assigns(name)) return true;
+      }
+      return false;
+    };
+
+    return Obj;
+
+  })(Base);
+
+  exports.Arr = Arr = (function(_super) {
+
+    __extends(Arr, _super);
+
+    function Arr(objs) {
+      this.objects = objs || [];
+    }
+
+    Arr.prototype.children = ['objects'];
+
+    Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects;
+
+    Arr.prototype.compileNode = function(o) {
+      var code, obj, objs;
+      if (!this.objects.length) return '[]';
+      o.indent += TAB;
+      objs = this.filterImplicitObjects(this.objects);
+      if (code = Splat.compileSplattedArray(o, objs)) return code;
+      code = ((function() {
+        var _i, _len, _results;
+        _results = [];
+        for (_i = 0, _len = objs.length; _i < _len; _i++) {
+          obj = objs[_i];
+          _results.push(obj.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })()).join(', ');
+      if (code.indexOf('\n') >= 0) {
+        return "[\n" + o.indent + code + "\n" + this.tab + "]";
+      } else {
+        return "[" + code + "]";
+      }
+    };
+
+    Arr.prototype.assigns = function(name) {
+      var obj, _i, _len, _ref2;
+      _ref2 = this.objects;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        obj = _ref2[_i];
+        if (obj.assigns(name)) return true;
+      }
+      return false;
+    };
+
+    return Arr;
+
+  })(Base);
+
+  exports.Class = Class = (function(_super) {
+
+    __extends(Class, _super);
+
+    function Class(variable, parent, body) {
+      this.variable = variable;
+      this.parent = parent;
+      this.body = body != null ? body : new Block;
+      this.boundFuncs = [];
+      this.body.classBody = true;
+    }
+
+    Class.prototype.children = ['variable', 'parent', 'body'];
+
+    Class.prototype.determineName = function() {
+      var decl, tail;
+      if (!this.variable) return null;
+      decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value;
+      return decl && (decl = IDENTIFIER.test(decl) && decl);
+    };
+
+    Class.prototype.setContext = function(name) {
+      return this.body.traverseChildren(false, function(node) {
+        if (node.classBody) return false;
+        if (node instanceof Literal && node.value === 'this') {
+          return node.value = name;
+        } else if (node instanceof Code) {
+          node.klass = name;
+          if (node.bound) return node.context = name;
+        }
+      });
+    };
+
+    Class.prototype.addBoundFunctions = function(o) {
+      var bvar, lhs, _i, _len, _ref2, _results;
+      if (this.boundFuncs.length) {
+        _ref2 = this.boundFuncs;
+        _results = [];
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          bvar = _ref2[_i];
+          lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
+          _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)")));
+        }
+        return _results;
+      }
+    };
+
+    Class.prototype.addProperties = function(node, name, o) {
+      var assign, base, exprs, func, props;
+      props = node.base.properties.slice(0);
+      exprs = (function() {
+        var _results;
+        _results = [];
+        while (assign = props.shift()) {
+          if (assign instanceof Assign) {
+            base = assign.variable.base;
+            delete assign.context;
+            func = assign.value;
+            if (base.value === 'constructor') {
+              if (this.ctor) {
+                throw new Error('cannot define more than one constructor in a class');
+              }
+              if (func.bound) {
+                throw new Error('cannot define a constructor as a bound function');
+              }
+              if (func instanceof Code) {
+                assign = this.ctor = func;
+              } else {
+                this.externalCtor = o.scope.freeVariable('class');
+                assign = new Assign(new Literal(this.externalCtor), func);
+              }
+            } else {
+              if (assign.variable["this"]) {
+                func.static = true;
+                if (func.bound) func.context = name;
+              } else {
+                assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
+                if (func instanceof Code && func.bound) {
+                  this.boundFuncs.push(base);
+                  func.bound = false;
+                }
+              }
+            }
+          }
+          _results.push(assign);
+        }
+        return _results;
+      }).call(this);
+      return compact(exprs);
+    };
+
+    Class.prototype.walkBody = function(name, o) {
+      var _this = this;
+      return this.traverseChildren(false, function(child) {
+        var exps, i, node, _len, _ref2;
+        if (child instanceof Class) return false;
+        if (child instanceof Block) {
+          _ref2 = exps = child.expressions;
+          for (i = 0, _len = _ref2.length; i < _len; i++) {
+            node = _ref2[i];
+            if (node instanceof Value && node.isObject(true)) {
+              exps[i] = _this.addProperties(node, name, o);
+            }
+          }
+          return child.expressions = exps = flatten(exps);
+        }
+      });
+    };
+
+    Class.prototype.ensureConstructor = function(name) {
+      if (!this.ctor) {
+        this.ctor = new Code;
+        if (this.parent) {
+          this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)"));
+        }
+        if (this.externalCtor) {
+          this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)"));
+        }
+        this.body.expressions.unshift(this.ctor);
+      }
+      this.ctor.ctor = this.ctor.name = name;
+      this.ctor.klass = null;
+      return this.ctor.noReturn = true;
+    };
+
+    Class.prototype.compileNode = function(o) {
+      var call, decl, klass, lname, name;
+      decl = this.determineName();
+      name = decl || this.name || '_Class';
+      if (name.reserved) name = "_" + name;
+      lname = new Literal(name);
+      this.setContext(name);
+      this.walkBody(name, o);
+      this.ensureConstructor(name);
+      this.body.spaced = true;
+      if (!(this.ctor instanceof Code)) this.body.expressions.unshift(this.ctor);
+      this.body.expressions.push(lname);
+      this.addBoundFunctions(o);
+      call = Closure.wrap(this.body);
+      if (this.parent) {
+        this.superClass = new Literal(o.scope.freeVariable('super', false));
+        this.body.expressions.unshift(new Extends(lname, this.superClass));
+        call.args.push(this.parent);
+        call.variable.params.push(new Param(this.superClass));
+      }
+      klass = new Parens(call, true);
+      if (this.variable) klass = new Assign(this.variable, klass);
+      return klass.compile(o);
+    };
+
+    return Class;
+
+  })(Base);
+
+  exports.Assign = Assign = (function(_super) {
+
+    __extends(Assign, _super);
+
+    function Assign(variable, value, context, options) {
+      this.variable = variable;
+      this.value = value;
+      this.context = context;
+      this.param = options && options.param;
+      this.subpattern = options && options.subpattern;
+    }
+
+    Assign.prototype.children = ['variable', 'value'];
+
+    Assign.prototype.isStatement = function(o) {
+      return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0;
+    };
+
+    Assign.prototype.assigns = function(name) {
+      return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
+    };
+
+    Assign.prototype.unfoldSoak = function(o) {
+      return unfoldSoak(o, this, 'variable');
+    };
+
+    Assign.prototype.compileNode = function(o) {
+      var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5;
+      if (isValue = this.variable instanceof Value) {
+        if (this.variable.isArray() || this.variable.isObject()) {
+          return this.compilePatternMatch(o);
+        }
+        if (this.variable.isSplice()) return this.compileSplice(o);
+        if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') {
+          return this.compileConditional(o);
+        }
+      }
+      name = this.variable.compile(o, LEVEL_LIST);
+      if (!this.context) {
+        if (!(varBase = this.variable.unwrapAll()).isAssignable()) {
+          throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned.");
+        }
+        if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) {
+          if (this.param) {
+            o.scope.add(name, 'var');
+          } else {
+            o.scope.find(name);
+          }
+        }
+      }
+      if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) {
+        if (match[1]) this.value.klass = match[1];
+        this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5];
+      }
+      val = this.value.compile(o, LEVEL_LIST);
+      if (this.context === 'object') return "" + name + ": " + val;
+      val = name + (" " + (this.context || '=') + " ") + val;
+      if (o.level <= LEVEL_LIST) {
+        return val;
+      } else {
+        return "(" + val + ")";
+      }
+    };
+
+    Assign.prototype.compilePatternMatch = function(o) {
+      var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
+      top = o.level === LEVEL_TOP;
+      value = this.value;
+      objects = this.variable.base.objects;
+      if (!(olen = objects.length)) {
+        code = value.compile(o);
+        if (o.level >= LEVEL_OP) {
+          return "(" + code + ")";
+        } else {
+          return code;
+        }
+      }
+      isObject = this.variable.isObject();
+      if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {
+        if (obj instanceof Assign) {
+          _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value;
+        } else {
+          if (obj.base instanceof Parens) {
+            _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1];
+          } else {
+            idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0);
+          }
+        }
+        acc = IDENTIFIER.test(idx.unwrap().value || 0);
+        value = new Value(value);
+        value.properties.push(new (acc ? Access : Index)(idx));
+        if (_ref5 = obj.unwrap().value, __indexOf.call(['arguments', 'eval'].concat(RESERVED), _ref5) >= 0) {
+          throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o)));
+        }
+        return new Assign(obj, value, null, {
+          param: this.param
+        }).compile(o, LEVEL_TOP);
+      }
+      vvar = value.compile(o, LEVEL_LIST);
+      assigns = [];
+      splat = false;
+      if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) {
+        assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar);
+        vvar = ref;
+      }
+      for (i = 0, _len = objects.length; i < _len; i++) {
+        obj = objects[i];
+        idx = i;
+        if (isObject) {
+          if (obj instanceof Assign) {
+            _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value;
+          } else {
+            if (obj.base instanceof Parens) {
+              _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1];
+            } else {
+              idx = obj["this"] ? obj.properties[0].name : obj;
+            }
+          }
+        }
+        if (!splat && obj instanceof Splat) {
+          name = obj.name.unwrap().value;
+          obj = obj.unwrap();
+          val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i;
+          if (rest = olen - i - 1) {
+            ivar = o.scope.freeVariable('i');
+            val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])";
+          } else {
+            val += ") : []";
+          }
+          val = new Literal(val);
+          splat = "" + ivar + "++";
+        } else {
+          name = obj.unwrap().value;
+          if (obj instanceof Splat) {
+            obj = obj.name.compile(o);
+            throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "...");
+          }
+          if (typeof idx === 'number') {
+            idx = new Literal(splat || idx);
+            acc = false;
+          } else {
+            acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);
+          }
+          val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
+        }
+        if ((name != null) && __indexOf.call(['arguments', 'eval'].concat(RESERVED), name) >= 0) {
+          throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o)));
+        }
+        assigns.push(new Assign(obj, val, null, {
+          param: this.param,
+          subpattern: true
+        }).compile(o, LEVEL_LIST));
+      }
+      if (!(top || this.subpattern)) assigns.push(vvar);
+      code = assigns.join(', ');
+      if (o.level < LEVEL_LIST) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+
+    Assign.prototype.compileConditional = function(o) {
+      var left, rite, _ref2;
+      _ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1];
+      if (__indexOf.call(this.context, "?") >= 0) o.isExistentialEquals = true;
+      return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o);
+    };
+
+    Assign.prototype.compileSplice = function(o) {
+      var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4;
+      _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive;
+      name = this.variable.compile(o);
+      _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1];
+      if (to) {
+        if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {
+          to = +to.compile(o) - +fromRef;
+          if (!exclusive) to += 1;
+        } else {
+          to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef;
+          if (!exclusive) to += ' + 1';
+        }
+      } else {
+        to = "9e9";
+      }
+      _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1];
+      code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef;
+      if (o.level > LEVEL_TOP) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+
+    return Assign;
+
+  })(Base);
+
+  exports.Code = Code = (function(_super) {
+
+    __extends(Code, _super);
+
+    function Code(params, body, tag) {
+      this.params = params || [];
+      this.body = body || new Block;
+      this.bound = tag === 'boundfunc';
+      if (this.bound) this.context = '_this';
+    }
+
+    Code.prototype.children = ['params', 'body'];
+
+    Code.prototype.isStatement = function() {
+      return !!this.ctor;
+    };
+
+    Code.prototype.jumps = NO;
+
+    Code.prototype.compileNode = function(o) {
+      var code, exprs, i, idt, lit, p, param, ref, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref2, _ref3, _ref4, _ref5, _ref6;
+      o.scope = new Scope(o.scope, this.body, this);
+      o.scope.shared = del(o, 'sharedScope');
+      o.indent += TAB;
+      delete o.bare;
+      vars = [];
+      exprs = [];
+      _ref2 = this.params;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        param = _ref2[_i];
+        if (!param.splat) continue;
+        _ref3 = this.params;
+        for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
+          p = _ref3[_j];
+          if (p.name.value) o.scope.add(p.name.value, 'var', true);
+        }
+        splats = new Assign(new Value(new Arr((function() {
+          var _k, _len3, _ref4, _results;
+          _ref4 = this.params;
+          _results = [];
+          for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
+            p = _ref4[_k];
+            _results.push(p.asReference(o));
+          }
+          return _results;
+        }).call(this))), new Value(new Literal('arguments')));
+        break;
+      }
+      _ref4 = this.params;
+      for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
+        param = _ref4[_k];
+        if (param.isComplex()) {
+          val = ref = param.asReference(o);
+          if (param.value) val = new Op('?', ref, param.value);
+          exprs.push(new Assign(new Value(param.name), val, '=', {
+            param: true
+          }));
+        } else {
+          ref = param;
+          if (param.value) {
+            lit = new Literal(ref.name.value + ' == null');
+            val = new Assign(new Value(param.name), param.value, '=');
+            exprs.push(new If(lit, val));
+          }
+        }
+        if (!splats) vars.push(ref);
+      }
+      wasEmpty = this.body.isEmpty();
+      if (splats) exprs.unshift(splats);
+      if (exprs.length) {
+        (_ref5 = this.body.expressions).unshift.apply(_ref5, exprs);
+      }
+      if (!splats) {
+        for (i = 0, _len4 = vars.length; i < _len4; i++) {
+          v = vars[i];
+          o.scope.parameter(vars[i] = v.compile(o));
+        }
+      }
+      if (!(wasEmpty || this.noReturn)) this.body.makeReturn();
+      if (this.bound) {
+        if ((_ref6 = o.scope.parent.method) != null ? _ref6.bound : void 0) {
+          this.bound = this.context = o.scope.parent.method.context;
+        } else if (!this.static) {
+          o.scope.parent.assign('_this', 'this');
+        }
+      }
+      idt = o.indent;
+      code = 'function';
+      if (this.ctor) code += ' ' + this.name;
+      code += '(' + vars.join(', ') + ') {';
+      if (!this.body.isEmpty()) {
+        code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab;
+      }
+      code += '}';
+      if (this.ctor) return this.tab + code;
+      if (this.front || (o.level >= LEVEL_ACCESS)) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+
+    Code.prototype.traverseChildren = function(crossScope, func) {
+      if (crossScope) {
+        return Code.__super__.traverseChildren.call(this, crossScope, func);
+      }
+    };
+
+    return Code;
+
+  })(Base);
+
+  exports.Param = Param = (function(_super) {
+
+    __extends(Param, _super);
+
+    function Param(name, value, splat) {
+      this.name = name;
+      this.value = value;
+      this.splat = splat;
+    }
+
+    Param.prototype.children = ['name', 'value'];
+
+    Param.prototype.compile = function(o) {
+      return this.name.compile(o, LEVEL_LIST);
+    };
+
+    Param.prototype.asReference = function(o) {
+      var node;
+      if (this.reference) return this.reference;
+      node = this.name;
+      if (node["this"]) {
+        node = node.properties[0].name;
+        if (node.value.reserved) node = new Literal('_' + node.value);
+      } else if (node.isComplex()) {
+        node = new Literal(o.scope.freeVariable('arg'));
+      }
+      node = new Value(node);
+      if (this.splat) node = new Splat(node);
+      return this.reference = node;
+    };
+
+    Param.prototype.isComplex = function() {
+      return this.name.isComplex();
+    };
+
+    return Param;
+
+  })(Base);
+
+  exports.Splat = Splat = (function(_super) {
+
+    __extends(Splat, _super);
+
+    Splat.prototype.children = ['name'];
+
+    Splat.prototype.isAssignable = YES;
+
+    function Splat(name) {
+      this.name = name.compile ? name : new Literal(name);
+    }
+
+    Splat.prototype.assigns = function(name) {
+      return this.name.assigns(name);
+    };
+
+    Splat.prototype.compile = function(o) {
+      if (this.index != null) {
+        return this.compileParam(o);
+      } else {
+        return this.name.compile(o);
+      }
+    };
+
+    Splat.prototype.unwrap = function() {
+      return this.name;
+    };
+
+    Splat.compileSplattedArray = function(o, list, apply) {
+      var args, base, code, i, index, node, _len;
+      index = -1;
+      while ((node = list[++index]) && !(node instanceof Splat)) {
+        continue;
+      }
+      if (index >= list.length) return '';
+      if (list.length === 1) {
+        code = list[0].compile(o, LEVEL_LIST);
+        if (apply) return code;
+        return "" + (utility('slice')) + ".call(" + code + ")";
+      }
+      args = list.slice(index);
+      for (i = 0, _len = args.length; i < _len; i++) {
+        node = args[i];
+        code = node.compile(o, LEVEL_LIST);
+        args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]";
+      }
+      if (index === 0) {
+        return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")");
+      }
+      base = (function() {
+        var _i, _len2, _ref2, _results;
+        _ref2 = list.slice(0, index);
+        _results = [];
+        for (_i = 0, _len2 = _ref2.length; _i < _len2; _i++) {
+          node = _ref2[_i];
+          _results.push(node.compile(o, LEVEL_LIST));
+        }
+        return _results;
+      })();
+      return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")";
+    };
+
+    return Splat;
+
+  })(Base);
+
+  exports.While = While = (function(_super) {
+
+    __extends(While, _super);
+
+    function While(condition, options) {
+      this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
+      this.guard = options != null ? options.guard : void 0;
+    }
+
+    While.prototype.children = ['condition', 'guard', 'body'];
+
+    While.prototype.isStatement = YES;
+
+    While.prototype.makeReturn = function(res) {
+      if (res) {
+        return While.__super__.makeReturn.apply(this, arguments);
+      } else {
+        this.returns = !this.jumps({
+          loop: true
+        });
+        return this;
+      }
+    };
+
+    While.prototype.addBody = function(body) {
+      this.body = body;
+      return this;
+    };
+
+    While.prototype.jumps = function() {
+      var expressions, node, _i, _len;
+      expressions = this.body.expressions;
+      if (!expressions.length) return false;
+      for (_i = 0, _len = expressions.length; _i < _len; _i++) {
+        node = expressions[_i];
+        if (node.jumps({
+          loop: true
+        })) return node;
+      }
+      return false;
+    };
+
+    While.prototype.compileNode = function(o) {
+      var body, code, rvar, set;
+      o.indent += TAB;
+      set = '';
+      body = this.body;
+      if (body.isEmpty()) {
+        body = '';
+      } else {
+        if (this.returns) {
+          body.makeReturn(rvar = o.scope.freeVariable('results'));
+          set = "" + this.tab + rvar + " = [];\n";
+        }
+        if (this.guard) {
+          if (body.expressions.length > 1) {
+            body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
+          } else {
+            if (this.guard) body = Block.wrap([new If(this.guard, body)]);
+          }
+        }
+        body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab;
+      }
+      code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}");
+      if (this.returns) code += "\n" + this.tab + "return " + rvar + ";";
+      return code;
+    };
+
+    return While;
+
+  })(Base);
+
+  exports.Op = Op = (function(_super) {
+    var CONVERSIONS, INVERSIONS;
+
+    __extends(Op, _super);
+
+    function Op(op, first, second, flip) {
+      var call;
+      if (op === 'in') return new In(first, second);
+      if (op === 'do') {
+        call = new Call(first, first.params || []);
+        call["do"] = true;
+        return call;
+      }
+      if (op === 'new') {
+        if (first instanceof Call && !first["do"] && !first.isNew) {
+          return first.newInstance();
+        }
+        if (first instanceof Code && first.bound || first["do"]) {
+          first = new Parens(first);
+        }
+      }
+      this.operator = CONVERSIONS[op] || op;
+      this.first = first;
+      this.second = second;
+      this.flip = !!flip;
+      return this;
+    }
+
+    CONVERSIONS = {
+      '==': '===',
+      '!=': '!==',
+      'of': 'in'
+    };
+
+    INVERSIONS = {
+      '!==': '===',
+      '===': '!=='
+    };
+
+    Op.prototype.children = ['first', 'second'];
+
+    Op.prototype.isSimpleNumber = NO;
+
+    Op.prototype.isUnary = function() {
+      return !this.second;
+    };
+
+    Op.prototype.isComplex = function() {
+      var _ref2;
+      return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex();
+    };
+
+    Op.prototype.isChainable = function() {
+      var _ref2;
+      return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!==';
+    };
+
+    Op.prototype.invert = function() {
+      var allInvertable, curr, fst, op, _ref2;
+      if (this.isChainable() && this.first.isChainable()) {
+        allInvertable = true;
+        curr = this;
+        while (curr && curr.operator) {
+          allInvertable && (allInvertable = curr.operator in INVERSIONS);
+          curr = curr.first;
+        }
+        if (!allInvertable) return new Parens(this).invert();
+        curr = this;
+        while (curr && curr.operator) {
+          curr.invert = !curr.invert;
+          curr.operator = INVERSIONS[curr.operator];
+          curr = curr.first;
+        }
+        return this;
+      } else if (op = INVERSIONS[this.operator]) {
+        this.operator = op;
+        if (this.first.unwrap() instanceof Op) this.first.invert();
+        return this;
+      } else if (this.second) {
+        return new Parens(this).invert();
+      } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) {
+        return fst;
+      } else {
+        return new Op('!', this);
+      }
+    };
+
+    Op.prototype.unfoldSoak = function(o) {
+      var _ref2;
+      return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first');
+    };
+
+    Op.prototype.compileNode = function(o) {
+      var code, isChain;
+      isChain = this.isChainable() && this.first.isChainable();
+      if (!isChain) this.first.front = this.front;
+      if (this.isUnary()) return this.compileUnary(o);
+      if (isChain) return this.compileChain(o);
+      if (this.operator === '?') return this.compileExistence(o);
+      code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP);
+      if (o.level <= LEVEL_OP) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+
+    Op.prototype.compileChain = function(o) {
+      var code, fst, shared, _ref2;
+      _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1];
+      fst = this.first.compile(o, LEVEL_OP);
+      code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP));
+      return "(" + code + ")";
+    };
+
+    Op.prototype.compileExistence = function(o) {
+      var fst, ref;
+      if (this.first.isComplex() && o.level > LEVEL_TOP) {
+        ref = new Literal(o.scope.freeVariable('ref'));
+        fst = new Parens(new Assign(ref, this.first));
+      } else {
+        fst = this.first;
+        ref = fst;
+      }
+      return new If(new Existence(fst), ref, {
+        type: 'if'
+      }).addElse(this.second).compile(o);
+    };
+
+    Op.prototype.compileUnary = function(o) {
+      var op, parts, plusMinus;
+      parts = [op = this.operator];
+      plusMinus = op === '+' || op === '-';
+      if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) {
+        parts.push(' ');
+      }
+      if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) {
+        this.first = new Parens(this.first);
+      }
+      parts.push(this.first.compile(o, LEVEL_OP));
+      if (this.flip) parts.reverse();
+      return parts.join('');
+    };
+
+    Op.prototype.toString = function(idt) {
+      return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
+    };
+
+    return Op;
+
+  })(Base);
+
+  exports.In = In = (function(_super) {
+
+    __extends(In, _super);
+
+    function In(object, array) {
+      this.object = object;
+      this.array = array;
+    }
+
+    In.prototype.children = ['object', 'array'];
+
+    In.prototype.invert = NEGATE;
+
+    In.prototype.compileNode = function(o) {
+      var hasSplat, obj, _i, _len, _ref2;
+      if (this.array instanceof Value && this.array.isArray()) {
+        _ref2 = this.array.base.objects;
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          obj = _ref2[_i];
+          if (!(obj instanceof Splat)) continue;
+          hasSplat = true;
+          break;
+        }
+        if (!hasSplat) return this.compileOrTest(o);
+      }
+      return this.compileLoopTest(o);
+    };
+
+    In.prototype.compileOrTest = function(o) {
+      var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3;
+      if (this.array.base.objects.length === 0) return "" + (!!this.negated);
+      _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1];
+      _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];
+      tests = (function() {
+        var _len, _ref4, _results;
+        _ref4 = this.array.base.objects;
+        _results = [];
+        for (i = 0, _len = _ref4.length; i < _len; i++) {
+          item = _ref4[i];
+          _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS));
+        }
+        return _results;
+      }).call(this);
+      tests = tests.join(cnj);
+      if (o.level < LEVEL_OP) {
+        return tests;
+      } else {
+        return "(" + tests + ")";
+      }
+    };
+
+    In.prototype.compileLoopTest = function(o) {
+      var code, ref, sub, _ref2;
+      _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1];
+      code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0');
+      if (sub === ref) return code;
+      code = sub + ', ' + code;
+      if (o.level < LEVEL_LIST) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+
+    In.prototype.toString = function(idt) {
+      return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
+    };
+
+    return In;
+
+  })(Base);
+
+  exports.Try = Try = (function(_super) {
+
+    __extends(Try, _super);
+
+    function Try(attempt, error, recovery, ensure) {
+      this.attempt = attempt;
+      this.error = error;
+      this.recovery = recovery;
+      this.ensure = ensure;
+    }
+
+    Try.prototype.children = ['attempt', 'recovery', 'ensure'];
+
+    Try.prototype.isStatement = YES;
+
+    Try.prototype.jumps = function(o) {
+      var _ref2;
+      return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0);
+    };
+
+    Try.prototype.makeReturn = function(res) {
+      if (this.attempt) this.attempt = this.attempt.makeReturn(res);
+      if (this.recovery) this.recovery = this.recovery.makeReturn(res);
+      return this;
+    };
+
+    Try.prototype.compileNode = function(o) {
+      var catchPart, ensurePart, errorPart, tryPart;
+      o.indent += TAB;
+      errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
+      tryPart = this.attempt.compile(o, LEVEL_TOP);
+      catchPart = this.recovery ? (!o.scope.check(this.error.value) ? o.scope.add(this.error.value, 'param') : void 0, " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}") : !(this.ensure || this.recovery) ? ' catch (_error) {}' : void 0;
+      ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : '';
+      return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart;
+    };
+
+    return Try;
+
+  })(Base);
+
+  exports.Throw = Throw = (function(_super) {
+
+    __extends(Throw, _super);
+
+    function Throw(expression) {
+      this.expression = expression;
+    }
+
+    Throw.prototype.children = ['expression'];
+
+    Throw.prototype.isStatement = YES;
+
+    Throw.prototype.jumps = NO;
+
+    Throw.prototype.makeReturn = THIS;
+
+    Throw.prototype.compileNode = function(o) {
+      return this.tab + ("throw " + (this.expression.compile(o)) + ";");
+    };
+
+    return Throw;
+
+  })(Base);
+
+  exports.Existence = Existence = (function(_super) {
+
+    __extends(Existence, _super);
+
+    function Existence(expression) {
+      this.expression = expression;
+    }
+
+    Existence.prototype.children = ['expression'];
+
+    Existence.prototype.invert = NEGATE;
+
+    Existence.prototype.compileNode = function(o) {
+      var cmp, cnj, code, _ref2;
+      this.expression.front = this.front;
+      code = this.expression.compile(o, LEVEL_OP);
+      if (IDENTIFIER.test(code) && !o.scope.check(code)) {
+        _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1];
+        code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null";
+      } else {
+        code = "" + code + " " + (this.negated ? '==' : '!=') + " null";
+      }
+      if (o.level <= LEVEL_COND) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+
+    return Existence;
+
+  })(Base);
+
+  exports.Parens = Parens = (function(_super) {
+
+    __extends(Parens, _super);
+
+    function Parens(body) {
+      this.body = body;
+    }
+
+    Parens.prototype.children = ['body'];
+
+    Parens.prototype.unwrap = function() {
+      return this.body;
+    };
+
+    Parens.prototype.isComplex = function() {
+      return this.body.isComplex();
+    };
+
+    Parens.prototype.compileNode = function(o) {
+      var bare, code, expr;
+      expr = this.body.unwrap();
+      if (expr instanceof Value && expr.isAtomic()) {
+        expr.front = this.front;
+        return expr.compile(o);
+      }
+      code = expr.compile(o, LEVEL_PAREN);
+      bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns));
+      if (bare) {
+        return code;
+      } else {
+        return "(" + code + ")";
+      }
+    };
+
+    return Parens;
+
+  })(Base);
+
+  exports.For = For = (function(_super) {
+
+    __extends(For, _super);
+
+    function For(body, source) {
+      var _ref2;
+      this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;
+      this.body = Block.wrap([body]);
+      this.own = !!source.own;
+      this.object = !!source.object;
+      if (this.object) {
+        _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1];
+      }
+      if (this.index instanceof Value) {
+        throw SyntaxError('index cannot be a pattern matching expression');
+      }
+      this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;
+      this.pattern = this.name instanceof Value;
+      if (this.range && this.index) {
+        throw SyntaxError('indexes do not apply to range loops');
+      }
+      if (this.range && this.pattern) {
+        throw SyntaxError('cannot pattern match over range loops');
+      }
+      this.returns = false;
+    }
+
+    For.prototype.children = ['body', 'source', 'guard', 'step'];
+
+    For.prototype.compileNode = function(o) {
+      var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2;
+      body = Block.wrap([this.body]);
+      lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0;
+      if (lastJumps && lastJumps instanceof Return) this.returns = false;
+      source = this.range ? this.source.base : this.source;
+      scope = o.scope;
+      name = this.name && this.name.compile(o, LEVEL_LIST);
+      index = this.index && this.index.compile(o, LEVEL_LIST);
+      if (name && !this.pattern) {
+        scope.find(name, {
+          immediate: true
+        });
+      }
+      if (index) {
+        scope.find(index, {
+          immediate: true
+        });
+      }
+      if (this.returns) rvar = scope.freeVariable('results');
+      ivar = (this.range ? name : index) || scope.freeVariable('i');
+      if (this.step && !this.range) stepvar = scope.freeVariable("step");
+      if (this.pattern) name = ivar;
+      varPart = '';
+      guardPart = '';
+      defPart = '';
+      idt1 = this.tab + TAB;
+      if (this.range) {
+        forPart = source.compile(merge(o, {
+          index: ivar,
+          step: this.step
+        }));
+      } else {
+        svar = this.source.compile(o, LEVEL_LIST);
+        if ((name || this.own) && !IDENTIFIER.test(svar)) {
+          defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n";
+          svar = ref;
+        }
+        if (name && !this.pattern) {
+          namePart = "" + name + " = " + svar + "[" + ivar + "]";
+        }
+        if (!this.object) {
+          lvar = scope.freeVariable('len');
+          forVarPart = ("" + ivar + " = 0, " + lvar + " = " + svar + ".length") + (this.step ? ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)) : '');
+          stepPart = this.step ? "" + ivar + " += " + stepvar : "" + ivar + "++";
+          forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart;
+        }
+      }
+      if (this.returns) {
+        resultPart = "" + this.tab + rvar + " = [];\n";
+        returnResult = "\n" + this.tab + "return " + rvar + ";";
+        body.makeReturn(rvar);
+      }
+      if (this.guard) {
+        if (body.expressions.length > 1) {
+          body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
+        } else {
+          if (this.guard) body = Block.wrap([new If(this.guard, body)]);
+        }
+      }
+      if (this.pattern) {
+        body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")));
+      }
+      defPart += this.pluckDirectCall(o, body);
+      if (namePart) varPart = "\n" + idt1 + namePart + ";";
+      if (this.object) {
+        forPart = "" + ivar + " in " + svar;
+        if (this.own) {
+          guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;";
+        }
+      }
+      body = body.compile(merge(o, {
+        indent: idt1
+      }), LEVEL_TOP);
+      if (body) body = '\n' + body + '\n';
+      return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || '');
+    };
+
+    For.prototype.pluckDirectCall = function(o, body) {
+      var base, defs, expr, fn, idx, ref, val, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
+      defs = '';
+      _ref2 = body.expressions;
+      for (idx = 0, _len = _ref2.length; idx < _len; idx++) {
+        expr = _ref2[idx];
+        expr = expr.unwrapAll();
+        if (!(expr instanceof Call)) continue;
+        val = expr.variable.unwrapAll();
+        if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) {
+          continue;
+        }
+        fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val;
+        ref = new Literal(o.scope.freeVariable('fn'));
+        base = new Value(ref);
+        if (val.base) _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];
+        body.expressions[idx] = new Call(base, expr.args);
+        defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
+      }
+      return defs;
+    };
+
+    return For;
+
+  })(While);
+
+  exports.Switch = Switch = (function(_super) {
+
+    __extends(Switch, _super);
+
+    function Switch(subject, cases, otherwise) {
+      this.subject = subject;
+      this.cases = cases;
+      this.otherwise = otherwise;
+    }
+
+    Switch.prototype.children = ['subject', 'cases', 'otherwise'];
+
+    Switch.prototype.isStatement = YES;
+
+    Switch.prototype.jumps = function(o) {
+      var block, conds, _i, _len, _ref2, _ref3, _ref4;
+      if (o == null) {
+        o = {
+          block: true
+        };
+      }
+      _ref2 = this.cases;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1];
+        if (block.jumps(o)) return block;
+      }
+      return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0;
+    };
+
+    Switch.prototype.makeReturn = function(res) {
+      var pair, _i, _len, _ref2, _ref3;
+      _ref2 = this.cases;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        pair = _ref2[_i];
+        pair[1].makeReturn(res);
+      }
+      if (res) {
+        this.otherwise || (this.otherwise = new Block([new Literal('void 0')]));
+      }
+      if ((_ref3 = this.otherwise) != null) _ref3.makeReturn(res);
+      return this;
+    };
+
+    Switch.prototype.compileNode = function(o) {
+      var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _len, _len2, _ref2, _ref3, _ref4, _ref5;
+      idt1 = o.indent + TAB;
+      idt2 = o.indent = idt1 + TAB;
+      code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n");
+      _ref3 = this.cases;
+      for (i = 0, _len = _ref3.length; i < _len; i++) {
+        _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1];
+        _ref5 = flatten([conditions]);
+        for (_i = 0, _len2 = _ref5.length; _i < _len2; _i++) {
+          cond = _ref5[_i];
+          if (!this.subject) cond = cond.invert();
+          code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n");
+        }
+        if (body = block.compile(o, LEVEL_TOP)) code += body + '\n';
+        if (i === this.cases.length - 1 && !this.otherwise) break;
+        expr = this.lastNonComment(block.expressions);
+        if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) {
+          continue;
+        }
+        code += idt2 + 'break;\n';
+      }
+      if (this.otherwise && this.otherwise.expressions.length) {
+        code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n");
+      }
+      return code + this.tab + '}';
+    };
+
+    return Switch;
+
+  })(Base);
+
+  exports.If = If = (function(_super) {
+
+    __extends(If, _super);
+
+    function If(condition, body, options) {
+      this.body = body;
+      if (options == null) options = {};
+      this.condition = options.type === 'unless' ? condition.invert() : condition;
+      this.elseBody = null;
+      this.isChain = false;
+      this.soak = options.soak;
+    }
+
+    If.prototype.children = ['condition', 'body', 'elseBody'];
+
+    If.prototype.bodyNode = function() {
+      var _ref2;
+      return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0;
+    };
+
+    If.prototype.elseBodyNode = function() {
+      var _ref2;
+      return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0;
+    };
+
+    If.prototype.addElse = function(elseBody) {
+      if (this.isChain) {
+        this.elseBodyNode().addElse(elseBody);
+      } else {
+        this.isChain = elseBody instanceof If;
+        this.elseBody = this.ensureBlock(elseBody);
+      }
+      return this;
+    };
+
+    If.prototype.isStatement = function(o) {
+      var _ref2;
+      return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0);
+    };
+
+    If.prototype.jumps = function(o) {
+      var _ref2;
+      return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0);
+    };
+
+    If.prototype.compileNode = function(o) {
+      if (this.isStatement(o)) {
+        return this.compileStatement(o);
+      } else {
+        return this.compileExpression(o);
+      }
+    };
+
+    If.prototype.makeReturn = function(res) {
+      if (res) {
+        this.elseBody || (this.elseBody = new Block([new Literal('void 0')]));
+      }
+      this.body && (this.body = new Block([this.body.makeReturn(res)]));
+      this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)]));
+      return this;
+    };
+
+    If.prototype.ensureBlock = function(node) {
+      if (node instanceof Block) {
+        return node;
+      } else {
+        return new Block([node]);
+      }
+    };
+
+    If.prototype.compileStatement = function(o) {
+      var body, bodyc, child, cond, exeq, ifPart, _ref2;
+      child = del(o, 'chainChild');
+      exeq = del(o, 'isExistentialEquals');
+      if (exeq) {
+        return new If(this.condition.invert(), this.elseBodyNode(), {
+          type: 'if'
+        }).compile(o);
+      }
+      cond = this.condition.compile(o, LEVEL_PAREN);
+      o.indent += TAB;
+      body = this.ensureBlock(this.body);
+      bodyc = body.compile(o);
+      if (1 === ((_ref2 = body.expressions) != null ? _ref2.length : void 0) && !this.elseBody && !child && bodyc && cond && -1 === (bodyc.indexOf('\n')) && 80 > cond.length + bodyc.length) {
+        return "" + this.tab + "if (" + cond + ") " + (bodyc.replace(/^\s+/, ''));
+      }
+      if (bodyc) bodyc = "\n" + bodyc + "\n" + this.tab;
+      ifPart = "if (" + cond + ") {" + bodyc + "}";
+      if (!child) ifPart = this.tab + ifPart;
+      if (!this.elseBody) return ifPart;
+      return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}");
+    };
+
+    If.prototype.compileExpression = function(o) {
+      var alt, body, code, cond;
+      cond = this.condition.compile(o, LEVEL_COND);
+      body = this.bodyNode().compile(o, LEVEL_LIST);
+      alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0';
+      code = "" + cond + " ? " + body + " : " + alt;
+      if (o.level >= LEVEL_COND) {
+        return "(" + code + ")";
+      } else {
+        return code;
+      }
+    };
+
+    If.prototype.unfoldSoak = function() {
+      return this.soak && this;
+    };
+
+    return If;
+
+  })(Base);
+
+  Closure = {
+    wrap: function(expressions, statement, noReturn) {
+      var args, call, func, mentionsArgs, meth;
+      if (expressions.jumps()) return expressions;
+      func = new Code([], Block.wrap([expressions]));
+      args = [];
+      if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) {
+        meth = new Literal(mentionsArgs ? 'apply' : 'call');
+        args = [new Literal('this')];
+        if (mentionsArgs) args.push(new Literal('arguments'));
+        func = new Value(func, [new Access(meth)]);
+      }
+      func.noReturn = noReturn;
+      call = new Call(func, args);
+      if (statement) {
+        return Block.wrap([call]);
+      } else {
+        return call;
+      }
+    },
+    literalArgs: function(node) {
+      return node instanceof Literal && node.value === 'arguments' && !node.asKey;
+    },
+    literalThis: function(node) {
+      return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound);
+    }
+  };
+
+  unfoldSoak = function(o, parent, name) {
+    var ifn;
+    if (!(ifn = parent[name].unfoldSoak(o))) return;
+    parent[name] = ifn.body;
+    ifn.body = new Value(parent);
+    return ifn;
+  };
+
+  UTILITIES = {
+    "extends": function() {
+      return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }";
+    },
+    bind: function() {
+      return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
+    },
+    indexOf: function() {
+      return "Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }";
+    },
+    hasProp: function() {
+      return 'Object.prototype.hasOwnProperty';
+    },
+    slice: function() {
+      return 'Array.prototype.slice';
+    }
+  };
+
+  LEVEL_TOP = 1;
+
+  LEVEL_PAREN = 2;
+
+  LEVEL_LIST = 3;
+
+  LEVEL_COND = 4;
+
+  LEVEL_OP = 5;
+
+  LEVEL_ACCESS = 6;
+
+  TAB = '  ';
+
+  IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
+
+  IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$");
+
+  SIMPLENUM = /^[+-]?\d+$/;
+
+  METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$");
+
+  IS_STRING = /^['"]/;
+
+  utility = function(name) {
+    var ref;
+    ref = "__" + name;
+    Scope.root.assign(ref, UTILITIES[name]());
+    return ref;
+  };
+
+  multident = function(code, tab) {
+    code = code.replace(/\n/g, '$&' + tab);
+    return code.replace(/\s+$/, '');
+  };
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/optparse.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/optparse.js
new file mode 100644
index 0000000..5e0114c
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/optparse.js
@@ -0,0 +1,122 @@
+(function() {
+  var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
+
+  exports.OptionParser = OptionParser = (function() {
+
+    function OptionParser(rules, banner) {
+      this.banner = banner;
+      this.rules = buildRules(rules);
+    }
+
+    OptionParser.prototype.parse = function(args) {
+      var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, value, _i, _len, _len2, _ref;
+      options = {
+        arguments: [],
+        literals: []
+      };
+      originalArgs = args;
+      args = normalizeArguments(args);
+      for (i = 0, _len = args.length; i < _len; i++) {
+        arg = args[i];
+        if (arg === '--') {
+          pos = originalArgs.indexOf('--');
+          options.arguments = [originalArgs[1 + pos]];
+          options.literals = originalArgs.slice(2 + pos);
+          break;
+        }
+        isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
+        matchedRule = false;
+        _ref = this.rules;
+        for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
+          rule = _ref[_i];
+          if (rule.shortFlag === arg || rule.longFlag === arg) {
+            value = rule.hasArgument ? args[i += 1] : true;
+            options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
+            matchedRule = true;
+            break;
+          }
+        }
+        if (isOption && !matchedRule) {
+          throw new Error("unrecognized option: " + arg);
+        }
+        if (!isOption) {
+          options.arguments = originalArgs.slice(originalArgs.indexOf(arg));
+          break;
+        }
+      }
+      return options;
+    };
+
+    OptionParser.prototype.help = function() {
+      var letPart, lines, rule, spaces, _i, _len, _ref;
+      lines = [];
+      if (this.banner) lines.unshift("" + this.banner + "\n");
+      _ref = this.rules;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        rule = _ref[_i];
+        spaces = 15 - rule.longFlag.length;
+        spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
+        letPart = rule.shortFlag ? rule.shortFlag + ', ' : '    ';
+        lines.push('  ' + letPart + rule.longFlag + spaces + rule.description);
+      }
+      return "\n" + (lines.join('\n')) + "\n";
+    };
+
+    return OptionParser;
+
+  })();
+
+  LONG_FLAG = /^(--\w[\w\-]+)/;
+
+  SHORT_FLAG = /^(-\w)/;
+
+  MULTI_FLAG = /^-(\w{2,})/;
+
+  OPTIONAL = /\[(\w+(\*?))\]/;
+
+  buildRules = function(rules) {
+    var tuple, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = rules.length; _i < _len; _i++) {
+      tuple = rules[_i];
+      if (tuple.length < 3) tuple.unshift(null);
+      _results.push(buildRule.apply(null, tuple));
+    }
+    return _results;
+  };
+
+  buildRule = function(shortFlag, longFlag, description, options) {
+    var match;
+    if (options == null) options = {};
+    match = longFlag.match(OPTIONAL);
+    longFlag = longFlag.match(LONG_FLAG)[1];
+    return {
+      name: longFlag.substr(2),
+      shortFlag: shortFlag,
+      longFlag: longFlag,
+      description: description,
+      hasArgument: !!(match && match[1]),
+      isList: !!(match && match[2])
+    };
+  };
+
+  normalizeArguments = function(args) {
+    var arg, l, match, result, _i, _j, _len, _len2, _ref;
+    args = args.slice(0);
+    result = [];
+    for (_i = 0, _len = args.length; _i < _len; _i++) {
+      arg = args[_i];
+      if (match = arg.match(MULTI_FLAG)) {
+        _ref = match[1].split('');
+        for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
+          l = _ref[_j];
+          result.push('-' + l);
+        }
+      } else {
+        result.push(arg);
+      }
+    }
+    return result;
+  };
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/parser.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/parser.js
new file mode 100755
index 0000000..198b563
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/parser.js
@@ -0,0 +1,674 @@
+/* Jison generated parser */
+var parser = (function(){
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"BOOL":36,"Assignable":37,"=":38,"AssignObj":39,"ObjAssignable":40,":":41,"ThisProperty":42,"RETURN":43,"HERECOMMENT":44,"PARAM_START":45,"ParamList":46,"PARAM_END":47,"FuncGlyph":48,"->":49,"=>":50,"OptComma":51,",":52,"Param":53,"ParamVar":54,"...":55,"Array":56,"Object":57,"Splat":58,"SimpleAssignable":59,"Accessor":60,"Parenthetical":61,"Range":62,"This":63,".":64,"?.":65,"::":66,"Index":67,"INDEX_START":68,"IndexValue":69,"INDEX_END":70,"INDEX_SOAK":71,"Slice":72,"{":73,"AssignList":74,"}":75,"CLASS":76,"EXTENDS":77,"OptFuncExist":78,"Arguments":79,"SUPER":80,"FUNC_EXIST":81,"CALL_START":82,"CALL_END":83,"ArgList":84,"THIS":85,"@":86,"[":87,"]":88,"RangeDots":89,"..":90,"Arg":91,"SimpleArgs":92,"TRY":93,"Catch":94,"FINALLY":95,"CATCH":96,"THROW":97,"(":98,")":99,"WhileSource":100,"WHILE":101,"WHEN":102,"UNTIL":103,"Loop":104,"LOOP":105,"ForBody":106,"FOR":107,"ForStart":108,"ForSource":109,"ForVariables":110,"OWN":111,"ForValue":112,"FORIN":113,"FOROF":114,"BY":115,"SWITCH":116,"Whens":117,"ELSE":118,"When":119,"LEADING_WHEN":120,"IfBlock":121,"IF":122,"POST_IF":123,"UNARY":124,"-":125,"+":126,"--":127,"++":128,"?":129,"MATH":130,"SHIFT":131,"COMPARE":132,"LOGIC":133,"RELATION":134,"COMPOUND_ASSIGN":135,"$accept":0,"$end":1},
+terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"BOOL",38:"=",41:":",43:"RETURN",44:"HERECOMMENT",45:"PARAM_START",47:"PARAM_END",49:"->",50:"=>",52:",",55:"...",64:".",65:"?.",66:"::",68:"INDEX_START",70:"INDEX_END",71:"INDEX_SOAK",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"},
+productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[39,1],[39,3],[39,5],[39,1],[40,1],[40,1],[40,1],[10,2],[10,1],[11,1],[15,5],[15,2],[48,1],[48,1],[51,0],[51,1],[46,0],[46,1],[46,3],[53,1],[53,2],[53,3],[54,1],[54,1],[54,1],[54,1],[58,2],[59,1],[59,2],[59,2],[59,1],[37,1],[37,1],[37,1],[13,1],[13,1],[13,1],[13,1],[13,1],[60,2],[60,2],[60,2],[60,1],[60,1],[67,3],[67,2],[69,1],[69,1],[57,4],[74,0],[74,1],[74,3],[74,4],[74,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[78,0],[78,1],[79,2],[79,4],[63,1],[63,1],[42,2],[56,2],[56,4],[89,1],[89,1],[62,5],[72,3],[72,2],[72,2],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[19,2],[19,3],[19,4],[19,5],[94,3],[24,2],[61,3],[61,5],[100,2],[100,4],[100,2],[100,4],[20,2],[20,2],[20,2],[20,1],[104,2],[104,2],[21,2],[21,2],[21,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[22,5],[22,7],[22,4],[22,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],
+performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1:return this.$ = new yy.Block;
+break;
+case 2:return this.$ = $$[$0];
+break;
+case 3:return this.$ = $$[$0-1];
+break;
+case 4:this.$ = yy.Block.wrap([$$[$0]]);
+break;
+case 5:this.$ = $$[$0-2].push($$[$0]);
+break;
+case 6:this.$ = $$[$0-1];
+break;
+case 7:this.$ = $$[$0];
+break;
+case 8:this.$ = $$[$0];
+break;
+case 9:this.$ = $$[$0];
+break;
+case 10:this.$ = $$[$0];
+break;
+case 11:this.$ = new yy.Literal($$[$0]);
+break;
+case 12:this.$ = $$[$0];
+break;
+case 13:this.$ = $$[$0];
+break;
+case 14:this.$ = $$[$0];
+break;
+case 15:this.$ = $$[$0];
+break;
+case 16:this.$ = $$[$0];
+break;
+case 17:this.$ = $$[$0];
+break;
+case 18:this.$ = $$[$0];
+break;
+case 19:this.$ = $$[$0];
+break;
+case 20:this.$ = $$[$0];
+break;
+case 21:this.$ = $$[$0];
+break;
+case 22:this.$ = $$[$0];
+break;
+case 23:this.$ = $$[$0];
+break;
+case 24:this.$ = new yy.Block;
+break;
+case 25:this.$ = $$[$0-1];
+break;
+case 26:this.$ = new yy.Literal($$[$0]);
+break;
+case 27:this.$ = new yy.Literal($$[$0]);
+break;
+case 28:this.$ = new yy.Literal($$[$0]);
+break;
+case 29:this.$ = $$[$0];
+break;
+case 30:this.$ = new yy.Literal($$[$0]);
+break;
+case 31:this.$ = new yy.Literal($$[$0]);
+break;
+case 32:this.$ = new yy.Literal($$[$0]);
+break;
+case 33:this.$ = (function () {
+        var val;
+        val = new yy.Literal($$[$0]);
+        if ($$[$0] === 'undefined') val.isUndefined = true;
+        return val;
+      }());
+break;
+case 34:this.$ = new yy.Assign($$[$0-2], $$[$0]);
+break;
+case 35:this.$ = new yy.Assign($$[$0-3], $$[$0]);
+break;
+case 36:this.$ = new yy.Assign($$[$0-4], $$[$0-1]);
+break;
+case 37:this.$ = new yy.Value($$[$0]);
+break;
+case 38:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object');
+break;
+case 39:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object');
+break;
+case 40:this.$ = $$[$0];
+break;
+case 41:this.$ = $$[$0];
+break;
+case 42:this.$ = $$[$0];
+break;
+case 43:this.$ = $$[$0];
+break;
+case 44:this.$ = new yy.Return($$[$0]);
+break;
+case 45:this.$ = new yy.Return;
+break;
+case 46:this.$ = new yy.Comment($$[$0]);
+break;
+case 47:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]);
+break;
+case 48:this.$ = new yy.Code([], $$[$0], $$[$0-1]);
+break;
+case 49:this.$ = 'func';
+break;
+case 50:this.$ = 'boundfunc';
+break;
+case 51:this.$ = $$[$0];
+break;
+case 52:this.$ = $$[$0];
+break;
+case 53:this.$ = [];
+break;
+case 54:this.$ = [$$[$0]];
+break;
+case 55:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 56:this.$ = new yy.Param($$[$0]);
+break;
+case 57:this.$ = new yy.Param($$[$0-1], null, true);
+break;
+case 58:this.$ = new yy.Param($$[$0-2], $$[$0]);
+break;
+case 59:this.$ = $$[$0];
+break;
+case 60:this.$ = $$[$0];
+break;
+case 61:this.$ = $$[$0];
+break;
+case 62:this.$ = $$[$0];
+break;
+case 63:this.$ = new yy.Splat($$[$0-1]);
+break;
+case 64:this.$ = new yy.Value($$[$0]);
+break;
+case 65:this.$ = $$[$0-1].add($$[$0]);
+break;
+case 66:this.$ = new yy.Value($$[$0-1], [].concat($$[$0]));
+break;
+case 67:this.$ = $$[$0];
+break;
+case 68:this.$ = $$[$0];
+break;
+case 69:this.$ = new yy.Value($$[$0]);
+break;
+case 70:this.$ = new yy.Value($$[$0]);
+break;
+case 71:this.$ = $$[$0];
+break;
+case 72:this.$ = new yy.Value($$[$0]);
+break;
+case 73:this.$ = new yy.Value($$[$0]);
+break;
+case 74:this.$ = new yy.Value($$[$0]);
+break;
+case 75:this.$ = $$[$0];
+break;
+case 76:this.$ = new yy.Access($$[$0]);
+break;
+case 77:this.$ = new yy.Access($$[$0], 'soak');
+break;
+case 78:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])];
+break;
+case 79:this.$ = new yy.Access(new yy.Literal('prototype'));
+break;
+case 80:this.$ = $$[$0];
+break;
+case 81:this.$ = $$[$0-1];
+break;
+case 82:this.$ = yy.extend($$[$0], {
+          soak: true
+        });
+break;
+case 83:this.$ = new yy.Index($$[$0]);
+break;
+case 84:this.$ = new yy.Slice($$[$0]);
+break;
+case 85:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated);
+break;
+case 86:this.$ = [];
+break;
+case 87:this.$ = [$$[$0]];
+break;
+case 88:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 89:this.$ = $$[$0-3].concat($$[$0]);
+break;
+case 90:this.$ = $$[$0-5].concat($$[$0-2]);
+break;
+case 91:this.$ = new yy.Class;
+break;
+case 92:this.$ = new yy.Class(null, null, $$[$0]);
+break;
+case 93:this.$ = new yy.Class(null, $$[$0]);
+break;
+case 94:this.$ = new yy.Class(null, $$[$0-1], $$[$0]);
+break;
+case 95:this.$ = new yy.Class($$[$0]);
+break;
+case 96:this.$ = new yy.Class($$[$0-1], null, $$[$0]);
+break;
+case 97:this.$ = new yy.Class($$[$0-2], $$[$0]);
+break;
+case 98:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]);
+break;
+case 99:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 100:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 101:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]);
+break;
+case 102:this.$ = new yy.Call('super', $$[$0]);
+break;
+case 103:this.$ = false;
+break;
+case 104:this.$ = true;
+break;
+case 105:this.$ = [];
+break;
+case 106:this.$ = $$[$0-2];
+break;
+case 107:this.$ = new yy.Value(new yy.Literal('this'));
+break;
+case 108:this.$ = new yy.Value(new yy.Literal('this'));
+break;
+case 109:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this');
+break;
+case 110:this.$ = new yy.Arr([]);
+break;
+case 111:this.$ = new yy.Arr($$[$0-2]);
+break;
+case 112:this.$ = 'inclusive';
+break;
+case 113:this.$ = 'exclusive';
+break;
+case 114:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]);
+break;
+case 115:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 116:this.$ = new yy.Range($$[$0-1], null, $$[$0]);
+break;
+case 117:this.$ = new yy.Range(null, $$[$0], $$[$0-1]);
+break;
+case 118:this.$ = [$$[$0]];
+break;
+case 119:this.$ = $$[$0-2].concat($$[$0]);
+break;
+case 120:this.$ = $$[$0-3].concat($$[$0]);
+break;
+case 121:this.$ = $$[$0-2];
+break;
+case 122:this.$ = $$[$0-5].concat($$[$0-2]);
+break;
+case 123:this.$ = $$[$0];
+break;
+case 124:this.$ = $$[$0];
+break;
+case 125:this.$ = $$[$0];
+break;
+case 126:this.$ = [].concat($$[$0-2], $$[$0]);
+break;
+case 127:this.$ = new yy.Try($$[$0]);
+break;
+case 128:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]);
+break;
+case 129:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]);
+break;
+case 130:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]);
+break;
+case 131:this.$ = [$$[$0-1], $$[$0]];
+break;
+case 132:this.$ = new yy.Throw($$[$0]);
+break;
+case 133:this.$ = new yy.Parens($$[$0-1]);
+break;
+case 134:this.$ = new yy.Parens($$[$0-2]);
+break;
+case 135:this.$ = new yy.While($$[$0]);
+break;
+case 136:this.$ = new yy.While($$[$0-2], {
+          guard: $$[$0]
+        });
+break;
+case 137:this.$ = new yy.While($$[$0], {
+          invert: true
+        });
+break;
+case 138:this.$ = new yy.While($$[$0-2], {
+          invert: true,
+          guard: $$[$0]
+        });
+break;
+case 139:this.$ = $$[$0-1].addBody($$[$0]);
+break;
+case 140:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+break;
+case 141:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+break;
+case 142:this.$ = $$[$0];
+break;
+case 143:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]);
+break;
+case 144:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]]));
+break;
+case 145:this.$ = new yy.For($$[$0-1], $$[$0]);
+break;
+case 146:this.$ = new yy.For($$[$0-1], $$[$0]);
+break;
+case 147:this.$ = new yy.For($$[$0], $$[$0-1]);
+break;
+case 148:this.$ = {
+          source: new yy.Value($$[$0])
+        };
+break;
+case 149:this.$ = (function () {
+        $$[$0].own = $$[$0-1].own;
+        $$[$0].name = $$[$0-1][0];
+        $$[$0].index = $$[$0-1][1];
+        return $$[$0];
+      }());
+break;
+case 150:this.$ = $$[$0];
+break;
+case 151:this.$ = (function () {
+        $$[$0].own = true;
+        return $$[$0];
+      }());
+break;
+case 152:this.$ = $$[$0];
+break;
+case 153:this.$ = new yy.Value($$[$0]);
+break;
+case 154:this.$ = new yy.Value($$[$0]);
+break;
+case 155:this.$ = [$$[$0]];
+break;
+case 156:this.$ = [$$[$0-2], $$[$0]];
+break;
+case 157:this.$ = {
+          source: $$[$0]
+        };
+break;
+case 158:this.$ = {
+          source: $$[$0],
+          object: true
+        };
+break;
+case 159:this.$ = {
+          source: $$[$0-2],
+          guard: $$[$0]
+        };
+break;
+case 160:this.$ = {
+          source: $$[$0-2],
+          guard: $$[$0],
+          object: true
+        };
+break;
+case 161:this.$ = {
+          source: $$[$0-2],
+          step: $$[$0]
+        };
+break;
+case 162:this.$ = {
+          source: $$[$0-4],
+          guard: $$[$0-2],
+          step: $$[$0]
+        };
+break;
+case 163:this.$ = {
+          source: $$[$0-4],
+          step: $$[$0-2],
+          guard: $$[$0]
+        };
+break;
+case 164:this.$ = new yy.Switch($$[$0-3], $$[$0-1]);
+break;
+case 165:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]);
+break;
+case 166:this.$ = new yy.Switch(null, $$[$0-1]);
+break;
+case 167:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]);
+break;
+case 168:this.$ = $$[$0];
+break;
+case 169:this.$ = $$[$0-1].concat($$[$0]);
+break;
+case 170:this.$ = [[$$[$0-1], $$[$0]]];
+break;
+case 171:this.$ = [[$$[$0-2], $$[$0-1]]];
+break;
+case 172:this.$ = new yy.If($$[$0-1], $$[$0], {
+          type: $$[$0-2]
+        });
+break;
+case 173:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], {
+          type: $$[$0-2]
+        }));
+break;
+case 174:this.$ = $$[$0];
+break;
+case 175:this.$ = $$[$0-2].addElse($$[$0]);
+break;
+case 176:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+          type: $$[$0-1],
+          statement: true
+        });
+break;
+case 177:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+          type: $$[$0-1],
+          statement: true
+        });
+break;
+case 178:this.$ = new yy.Op($$[$0-1], $$[$0]);
+break;
+case 179:this.$ = new yy.Op('-', $$[$0]);
+break;
+case 180:this.$ = new yy.Op('+', $$[$0]);
+break;
+case 181:this.$ = new yy.Op('--', $$[$0]);
+break;
+case 182:this.$ = new yy.Op('++', $$[$0]);
+break;
+case 183:this.$ = new yy.Op('--', $$[$0-1], null, true);
+break;
+case 184:this.$ = new yy.Op('++', $$[$0-1], null, true);
+break;
+case 185:this.$ = new yy.Existence($$[$0-1]);
+break;
+case 186:this.$ = new yy.Op('+', $$[$0-2], $$[$0]);
+break;
+case 187:this.$ = new yy.Op('-', $$[$0-2], $$[$0]);
+break;
+case 188:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 189:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 190:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 191:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 192:this.$ = (function () {
+        if ($$[$0-1].charAt(0) === '!') {
+          return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();
+        } else {
+          return new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+        }
+      }());
+break;
+case 193:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]);
+break;
+case 194:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]);
+break;
+case 195:this.$ = new yy.Extends($$[$0-2], $$[$0]);
+break;
+}
+},
+table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,72]},{6:[1,73]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:75,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,74],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],47:[2,12],52:[2,12],55:[2,12],60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,12],71:[1,98],75:[2,12],78:90,81:[1,92],82:[2,103],83:[2,12],88:[2,12],90:[2,12],99:[2,12],101:[2,12],102:[2,12],103:[2,12],107:[2,12],115:[2,12],123:[2,12],125:[2,12],126:[2,12],129:[2,12],130:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],47:[2,13],52:[2,13],55:[2,13],60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,13],71:[1,98],75:[2,13],78:99,81:[1,92],82:[2,103],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],47:[2,14],52:[2,14],55:[2,14],70:[2,14],75:[2,14],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],47:[2,15],52:[2,15],55:[2,15],70:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],47:[2,16],52:[2,16],55:[2,16],70:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],47:[2,17],52:[2,17],55:[2,17],70:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],47:[2,18],52:[2,18],55:[2,18],70:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],47:[2,19],52:[2,19],55:[2,19],70:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],47:[2,20],52:[2,20],55:[2,20],70:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],47:[2,21],52:[2,21],55:[2,21],70:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],47:[2,22],52:[2,22],55:[2,22],70:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],47:[2,23],52:[2,23],55:[2,23],70:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],38:[1,101],47:[2,71],52:[2,71],55:[2,71],64:[2,71],65:[2,71],66:[2,71],68:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],47:[2,72],52:[2,72],55:[2,72],64:[2,72],65:[2,72],66:[2,72],68:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],47:[2,73],52:[2,73],55:[2,73],64:[2,73],65:[2,73],66:[2,73],68:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],47:[2,74],52:[2,74],55:[2,74],64:[2,74],65:[2,74],66:[2,74],68:[2,74],70:[2,74],71:[2,74],75:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],47:[2,75],52:[2,75],55:[2,75],64:[2,75],65:[2,75],66:[2,75],68:[2,75],70:[2,75],71:[2,75],75:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],47:[2,101],52:[2,101],55:[2,101],64:[2,101],65:[2,101],66:[2,101],68:[2,101],70:[2,101],71:[2,101],75:[2,101],79:102,81:[2,101],82:[1,103],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{27:107,28:[1,71],42:108,46:104,47:[2,53],52:[2,53],53:105,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:118,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:122,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],38:[2,68],47:[2,68],52:[2,68],55:[2,68],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,68],71:[2,68],75:[2,68],77:[1,126],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],127:[1,123],128:[1,124],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[1,125]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],47:[2,174],52:[2,174],55:[2,174],70:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],118:[1,127],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],47:[2,142],52:[2,142],55:[2,142],70:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{5:130,25:[1,5]},{8:131,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,132],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,91],5:133,6:[2,91],13:119,14:120,25:[1,5],26:[2,91],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,47:[2,91],52:[2,91],55:[2,91],56:47,57:48,59:135,61:25,62:26,63:27,70:[2,91],73:[1,68],75:[2,91],77:[1,134],80:[1,28],83:[2,91],85:[1,56],86:[1,57],87:[1,55],88:[2,91],90:[2,91],98:[1,54],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{8:136,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,45],6:[2,45],8:137,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,45],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,45],100:39,101:[2,45],103:[2,45],104:40,105:[1,65],106:41,107:[2,45],108:67,116:[1,42],121:37,122:[1,62],123:[2,45],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],52:[2,46],75:[2,46],99:[2,46],101:[2,46],103:[2,46],107:[2,46],123:[2,46]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],38:[2,69],47:[2,69],52:[2,69],55:[2,69],64:[2,69],65:[2,69],66:[2,69],68:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],38:[2,70],47:[2,70],52:[2,70],55:[2,70],64:[2,70],65:[2,70],66:[2,70],68:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],47:[2,29],52:[2,29],55:[2,29],64:[2,29],65:[2,29],66:[2,29],68:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],47:[2,30],52:[2,30],55:[2,30],64:[2,30],65:[2,30],66:[2,30],68:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],47:[2,31],52:[2,31],55:[2,31],64:[2,31],65:[2,31],66:[2,31],68:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],47:[2,32],52:[2,32],55:[2,32],64:[2,32],65:[2,32],66:[2,32],68:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],47:[2,33],52:[2,33],55:[2,33],64:[2,33],65:[2,33],66:[2,33],68:[2,33],70:[2,33],71:[2,33],75:[2,33],81:[2,33],82:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],101:[2,33],102:[2,33],103:[2,33],107:[2,33],115:[2,33],123:[2,33],125:[2,33],126:[2,33],129:[2,33],130:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33]},{4:138,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,139],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],47:[2,107],52:[2,107],55:[2,107],64:[2,107],65:[2,107],66:[2,107],68:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],27:146,28:[1,71],47:[2,108],52:[2,108],55:[2,108],64:[2,108],65:[2,108],66:[2,108],68:[2,108],70:[2,108],71:[2,108],75:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108]},{25:[2,49]},{25:[2,50]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],38:[2,64],47:[2,64],52:[2,64],55:[2,64],64:[2,64],65:[2,64],66:[2,64],68:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],38:[2,67],47:[2,67],52:[2,67],55:[2,67],64:[2,67],65:[2,67],66:[2,67],68:[2,67],70:[2,67],71:[2,67],75:[2,67],77:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67],135:[2,67]},{8:147,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,71],56:157,57:158,62:152,73:[1,68],87:[1,55],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,86],11:165,25:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:162,75:[2,86],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],41:[2,27],47:[2,27],52:[2,27],55:[2,27],64:[2,27],65:[2,27],66:[2,27],68:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],41:[2,28],47:[2,28],52:[2,28],55:[2,28],64:[2,28],65:[2,28],66:[2,28],68:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],38:[2,26],41:[2,26],47:[2,26],52:[2,26],55:[2,26],64:[2,26],65:[2,26],66:[2,26],68:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,6],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],47:[2,24],52:[2,24],55:[2,24],70:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,72],26:[1,170]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],47:[2,185],52:[2,185],55:[2,185],70:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],101:[2,185],102:[2,185],103:[2,185],107:[2,185],115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{8:171,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],47:[2,141],52:[2,141],55:[2,141],70:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],47:[2,146],52:[2,146],55:[2,146],70:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{8:179,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],47:[2,140],52:[2,140],55:[2,140],70:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],47:[2,145],52:[2,145],55:[2,145],70:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],101:[2,145],102:[2,145],103:[2,145],107:[2,145],115:[2,145],123:[2,145],125:[2,145],126:[2,145],129:[2,145],130:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145]},{79:180,82:[1,103]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],38:[2,65],47:[2,65],52:[2,65],55:[2,65],64:[2,65],65:[2,65],66:[2,65],68:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{82:[2,104]},{27:181,28:[1,71]},{27:182,28:[1,71]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],27:183,28:[1,71],38:[2,79],47:[2,79],52:[2,79],55:[2,79],64:[2,79],65:[2,79],66:[2,79],68:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],38:[2,80],47:[2,80],52:[2,80],55:[2,80],64:[2,80],65:[2,80],66:[2,80],68:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{8:185,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],55:[1,189],56:47,57:48,59:36,61:25,62:26,63:27,69:184,72:186,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],89:187,90:[1,188],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{67:190,68:[1,97],71:[1,98]},{79:191,82:[1,103]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],38:[2,66],47:[2,66],52:[2,66],55:[2,66],64:[2,66],65:[2,66],66:[2,66],68:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[2,66]},{6:[1,193],8:192,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,194],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],47:[2,102],52:[2,102],55:[2,102],64:[2,102],65:[2,102],66:[2,102],68:[2,102],70:[2,102],71:[2,102],75:[2,102],81:[2,102],82:[2,102],83:[2,102],88:[2,102],90:[2,102],99:[2,102],101:[2,102],102:[2,102],103:[2,102],107:[2,102],115:[2,102],123:[2,102],125:[2,102],126:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{47:[1,198],52:[1,199]},{47:[2,54],52:[2,54]},{38:[1,201],47:[2,56],52:[2,56],55:[1,200]},{38:[2,59],47:[2,59],52:[2,59],55:[2,59]},{38:[2,60],47:[2,60],52:[2,60],55:[2,60]},{38:[2,61],47:[2,61],52:[2,61],55:[2,61]},{38:[2,62],47:[2,62],52:[2,62],55:[2,62]},{27:146,28:[1,71]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],47:[2,48],52:[2,48],55:[2,48],70:[2,48],75:[2,48],83:[2,48],88:[2,48],90:[2,48],99:[2,48],101:[2,48],102:[2,48],103:[2,48],107:[2,48],115:[2,48],123:[2,48],125:[2,48],126:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],133:[2,48],134:[2,48]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],47:[2,178],52:[2,178],55:[2,178],70:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:85,101:[2,178],102:[2,178],103:[2,178],106:86,107:[2,178],108:67,115:[2,178],123:[2,178],125:[2,178],126:[2,178],129:[1,76],130:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178]},{100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],47:[2,179],52:[2,179],55:[2,179],70:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:85,101:[2,179],102:[2,179],103:[2,179],106:86,107:[2,179],108:67,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,76],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],47:[2,180],52:[2,180],55:[2,180],70:[2,180],75:[2,180],83:[2,180],88:[2,180],90:[2,180],99:[2,180],100:85,101:[2,180],102:[2,180],103:[2,180],106:86,107:[2,180],108:67,115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[1,76],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],47:[2,181],52:[2,181],55:[2,181],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,181],71:[2,68],75:[2,181],81:[2,68],82:[2,68],83:[2,181],88:[2,181],90:[2,181],99:[2,181],101:[2,181],102:[2,181],103:[2,181],107:[2,181],115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[2,181],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:90,81:[1,92],82:[2,103]},{60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:99,81:[1,92],82:[2,103]},{64:[2,71],65:[2,71],66:[2,71],68:[2,71],71:[2,71],81:[2,71],82:[2,71]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],47:[2,182],52:[2,182],55:[2,182],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,182],71:[2,68],75:[2,182],81:[2,68],82:[2,68],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],47:[2,183],52:[2,183],55:[2,183],70:[2,183],75:[2,183],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],47:[2,184],52:[2,184],55:[2,184],70:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{8:202,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,203],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,127],6:[2,127],25:[2,127],26:[2,127],47:[2,127],52:[2,127],55:[2,127],70:[2,127],75:[2,127],83:[2,127],88:[2,127],90:[2,127],94:207,95:[1,208],96:[1,209],99:[2,127],101:[2,127],102:[2,127],103:[2,127],107:[2,127],115:[2,127],123:[2,127],125:[2,127],126:[2,127],129:[2,127],130:[2,127],131:[2,127],132:[2,127],133:[2,127],134:[2,127]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],47:[2,139],52:[2,139],55:[2,139],70:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],101:[2,139],102:[2,139],103:[2,139],107:[2,139],115:[2,139],123:[2,139],125:[2,139],126:[2,139],129:[2,139],130:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],47:[2,147],52:[2,147],55:[2,147],70:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{25:[1,210],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{117:211,119:212,120:[1,213]},{1:[2,92],6:[2,92],25:[2,92],26:[2,92],47:[2,92],52:[2,92],55:[2,92],70:[2,92],75:[2,92],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{8:214,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,95],5:215,6:[2,95],25:[1,5],26:[2,95],47:[2,95],52:[2,95],55:[2,95],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,95],71:[2,68],75:[2,95],77:[1,216],81:[2,68],82:[2,68],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],47:[2,132],52:[2,132],55:[2,132],70:[2,132],75:[2,132],83:[2,132],88:[2,132],90:[2,132],99:[2,132],100:85,101:[2,132],102:[2,132],103:[2,132],106:86,107:[2,132],108:67,115:[2,132],123:[2,132],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,44],6:[2,44],26:[2,44],99:[2,44],100:85,101:[2,44],103:[2,44],106:86,107:[2,44],108:67,123:[2,44],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,72],99:[1,217]},{4:218,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,123],25:[2,123],52:[2,123],55:[1,220],88:[2,123],89:219,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],38:[2,110],47:[2,110],52:[2,110],55:[2,110],64:[2,110],65:[2,110],66:[2,110],68:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{6:[2,51],25:[2,51],51:221,52:[1,222],88:[2,51]},{6:[2,118],25:[2,118],26:[2,118],52:[2,118],83:[2,118],88:[2,118]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:223,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,124],25:[2,124],26:[2,124],52:[2,124],83:[2,124],88:[2,124]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],38:[2,109],41:[2,109],47:[2,109],52:[2,109],55:[2,109],64:[2,109],65:[2,109],66:[2,109],68:[2,109],70:[2,109],71:[2,109],75:[2,109],77:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109]},{5:224,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],47:[2,135],52:[2,135],55:[2,135],70:[2,135],75:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],100:85,101:[1,63],102:[1,225],103:[1,64],106:86,107:[1,66],108:67,115:[2,135],123:[2,135],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],47:[2,137],52:[2,137],55:[2,137],70:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:85,101:[1,63],102:[1,226],103:[1,64],106:86,107:[1,66],108:67,115:[2,137],123:[2,137],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],47:[2,143],52:[2,143],55:[2,143],70:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],101:[2,143],102:[2,143],103:[2,143],107:[2,143],115:[2,143],123:[2,143],125:[2,143],126:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],133:[2,143],134:[2,143]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],47:[2,144],52:[2,144],55:[2,144],70:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],100:85,101:[1,63],102:[2,144],103:[1,64],106:86,107:[1,66],108:67,115:[2,144],123:[2,144],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],47:[2,148],52:[2,148],55:[2,148],70:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{113:[2,150],114:[2,150]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],110:227,112:155},{52:[1,228],113:[2,155],114:[2,155]},{52:[2,152],113:[2,152],114:[2,152]},{52:[2,153],113:[2,153],114:[2,153]},{52:[2,154],113:[2,154],114:[2,154]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],47:[2,149],52:[2,149],55:[2,149],70:[2,149],75:[2,149],83:[2,149],88:[2,149],90:[2,149],99:[2,149],101:[2,149],102:[2,149],103:[2,149],107:[2,149],115:[2,149],123:[2,149],125:[2,149],126:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],133:[2,149],134:[2,149]},{8:229,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:230,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],51:231,52:[1,232],75:[2,51]},{6:[2,87],25:[2,87],26:[2,87],52:[2,87],75:[2,87]},{6:[2,37],25:[2,37],26:[2,37],41:[1,233],52:[2,37],75:[2,37]},{6:[2,40],25:[2,40],26:[2,40],52:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],41:[2,41],52:[2,41],75:[2,41]},{6:[2,42],25:[2,42],26:[2,42],41:[2,42],52:[2,42],75:[2,42]},{6:[2,43],25:[2,43],26:[2,43],41:[2,43],52:[2,43],75:[2,43]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],47:[2,25],52:[2,25],55:[2,25],70:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],47:[2,186],52:[2,186],55:[2,186],70:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],100:85,101:[2,186],102:[2,186],103:[2,186],106:86,107:[2,186],108:67,115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[1,76],130:[1,79],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],47:[2,187],52:[2,187],55:[2,187],70:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:85,101:[2,187],102:[2,187],103:[2,187],106:86,107:[2,187],108:67,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,76],130:[1,79],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],47:[2,188],52:[2,188],55:[2,188],70:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:85,101:[2,188],102:[2,188],103:[2,188],106:86,107:[2,188],108:67,115:[2,188],123:[2,188],125:[2,188],126:[2,188],129:[1,76],130:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],47:[2,189],52:[2,189],55:[2,189],70:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:85,101:[2,189],102:[2,189],103:[2,189],106:86,107:[2,189],108:67,115:[2,189],123:[2,189],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[2,189],132:[2,189],133:[2,189],134:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],47:[2,190],52:[2,190],55:[2,190],70:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:85,101:[2,190],102:[2,190],103:[2,190],106:86,107:[2,190],108:67,115:[2,190],123:[2,190],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,190],133:[2,190],134:[1,83]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],47:[2,191],52:[2,191],55:[2,191],70:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:85,101:[2,191],102:[2,191],103:[2,191],106:86,107:[2,191],108:67,115:[2,191],123:[2,191],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[2,191],134:[1,83]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],47:[2,192],52:[2,192],55:[2,192],70:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:85,101:[2,192],102:[2,192],103:[2,192],106:86,107:[2,192],108:67,115:[2,192],123:[2,192],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,192],133:[2,192],134:[2,192]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],47:[2,177],52:[2,177],55:[2,177],70:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:85,101:[1,63],102:[2,177],103:[1,64],106:86,107:[1,66],108:67,115:[2,177],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],47:[2,176],52:[2,176],55:[2,176],70:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],100:85,101:[1,63],102:[2,176],103:[1,64],106:86,107:[1,66],108:67,115:[2,176],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],47:[2,99],52:[2,99],55:[2,99],64:[2,99],65:[2,99],66:[2,99],68:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],38:[2,76],47:[2,76],52:[2,76],55:[2,76],64:[2,76],65:[2,76],66:[2,76],68:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],38:[2,77],47:[2,77],52:[2,77],55:[2,77],64:[2,77],65:[2,77],66:[2,77],68:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],38:[2,78],47:[2,78],52:[2,78],55:[2,78],64:[2,78],65:[2,78],66:[2,78],68:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{70:[1,234]},{55:[1,189],70:[2,83],89:235,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{70:[2,84]},{8:236,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{12:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],36:[2,112],43:[2,112],44:[2,112],45:[2,112],49:[2,112],50:[2,112],70:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{12:[2,113],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],70:[2,113],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],38:[2,82],47:[2,82],52:[2,82],55:[2,82],64:[2,82],65:[2,82],66:[2,82],68:[2,82],70:[2,82],71:[2,82],75:[2,82],77:[2,82],81:[2,82],82:[2,82],83:[2,82],88:[2,82],90:[2,82],99:[2,82],101:[2,82],102:[2,82],103:[2,82],107:[2,82],115:[2,82],123:[2,82],125:[2,82],126:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],47:[2,100],52:[2,100],55:[2,100],64:[2,100],65:[2,100],66:[2,100],68:[2,100],70:[2,100],71:[2,100],75:[2,100],81:[2,100],82:[2,100],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],47:[2,34],52:[2,34],55:[2,34],70:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],100:85,101:[2,34],102:[2,34],103:[2,34],106:86,107:[2,34],108:67,115:[2,34],123:[2,34],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:237,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:238,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],47:[2,105],52:[2,105],55:[2,105],64:[2,105],65:[2,105],66:[2,105],68:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{6:[2,51],25:[2,51],51:239,52:[1,222],83:[2,51]},{6:[2,123],25:[2,123],26:[2,123],52:[2,123],55:[1,240],83:[2,123],88:[2,123],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{48:241,49:[1,58],50:[1,59]},{27:107,28:[1,71],42:108,53:242,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{47:[2,57],52:[2,57]},{8:243,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],47:[2,193],52:[2,193],55:[2,193],70:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],100:85,101:[2,193],102:[2,193],103:[2,193],106:86,107:[2,193],108:67,115:[2,193],123:[2,193],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:244,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],47:[2,195],52:[2,195],55:[2,195],70:[2,195],75:[2,195],83:[2,195],88:[2,195],90:[2,195],99:[2,195],100:85,101:[2,195],102:[2,195],103:[2,195],106:86,107:[2,195],108:67,115:[2,195],123:[2,195],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],47:[2,175],52:[2,175],55:[2,175],70:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],101:[2,175],102:[2,175],103:[2,175],107:[2,175],115:[2,175],123:[2,175],125:[2,175],126:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],133:[2,175],134:[2,175]},{8:245,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],47:[2,128],52:[2,128],55:[2,128],70:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],95:[1,246],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{5:247,25:[1,5]},{27:248,28:[1,71]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,168],118:[2,168],120:[2,168]},{8:254,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],92:253,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,93],5:255,6:[2,93],25:[1,5],26:[2,93],47:[2,93],52:[2,93],55:[2,93],70:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],100:85,101:[1,63],102:[2,93],103:[1,64],106:86,107:[1,66],108:67,115:[2,93],123:[2,93],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],47:[2,96],52:[2,96],55:[2,96],70:[2,96],75:[2,96],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{8:256,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],47:[2,133],52:[2,133],55:[2,133],64:[2,133],65:[2,133],66:[2,133],68:[2,133],70:[2,133],71:[2,133],75:[2,133],81:[2,133],82:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],101:[2,133],102:[2,133],103:[2,133],107:[2,133],115:[2,133],123:[2,133],125:[2,133],126:[2,133],129:[2,133],130:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133]},{6:[1,72],26:[1,257]},{8:258,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,63],12:[2,113],25:[2,63],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],52:[2,63],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,63],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,52],8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,52],26:[2,52],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[2,52],85:[1,56],86:[1,57],87:[1,55],88:[2,52],91:262,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],26:[2,51],51:263,52:[1,222]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],47:[2,172],52:[2,172],55:[2,172],70:[2,172],75:[2,172],83:[2,172],88:[2,172],90:[2,172],99:[2,172],101:[2,172],102:[2,172],103:[2,172],107:[2,172],115:[2,172],118:[2,172],123:[2,172],125:[2,172],126:[2,172],129:[2,172],130:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172]},{8:264,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,151],114:[2,151]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],112:266},{1:[2,157],6:[2,157],25:[2,157],26:[2,157],47:[2,157],52:[2,157],55:[2,157],70:[2,157],75:[2,157],83:[2,157],88:[2,157],90:[2,157],99:[2,157],100:85,101:[2,157],102:[1,267],103:[2,157],106:86,107:[2,157],108:67,115:[1,268],123:[2,157],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],47:[2,158],52:[2,158],55:[2,158],70:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:85,101:[2,158],102:[1,269],103:[2,158],106:86,107:[2,158],108:67,115:[2,158],123:[2,158],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,52],11:165,25:[2,52],26:[2,52],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:273,40:164,42:168,44:[1,46],75:[2,52],86:[1,111]},{8:274,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,275],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],38:[2,81],47:[2,81],52:[2,81],55:[2,81],64:[2,81],65:[2,81],66:[2,81],68:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{8:276,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,116],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,117],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],47:[2,35],52:[2,35],55:[2,35],70:[2,35],75:[2,35],83:[2,35],88:[2,35],90:[2,35],99:[2,35],100:85,101:[2,35],102:[2,35],103:[2,35],106:86,107:[2,35],108:67,115:[2,35],123:[2,35],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,277],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,63],25:[2,63],26:[2,63],52:[2,63],83:[2,63],88:[2,63]},{5:279,25:[1,5]},{47:[2,55],52:[2,55]},{47:[2,58],52:[2,58],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,280],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:281,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:282,25:[1,5]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],47:[2,129],52:[2,129],55:[2,129],70:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],47:[2,166],52:[2,166],55:[2,166],70:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{5:286,25:[1,5]},{26:[2,169],118:[2,169],120:[2,169]},{5:287,25:[1,5],52:[1,288]},{25:[2,125],52:[2,125],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,94],6:[2,94],25:[2,94],26:[2,94],47:[2,94],52:[2,94],55:[2,94],70:[2,94],75:[2,94],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,97],5:289,6:[2,97],25:[1,5],26:[2,97],47:[2,97],52:[2,97],55:[2,97],70:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],100:85,101:[1,63],102:[2,97],103:[1,64],106:86,107:[1,66],108:67,115:[2,97],123:[2,97],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{99:[1,290]},{88:[1,291],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],38:[2,111],47:[2,111],52:[2,111],55:[2,111],64:[2,111],65:[2,111],66:[2,111],68:[2,111],70:[2,111],71:[2,111],75:[2,111],81:[2,111],82:[2,111],83:[2,111],88:[2,111],90:[2,111],99:[2,111],101:[2,111],102:[2,111],103:[2,111],107:[2,111],113:[2,111],114:[2,111],115:[2,111],123:[2,111],125:[2,111],126:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],91:292,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:293,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,119],25:[2,119],26:[2,119],52:[2,119],83:[2,119],88:[2,119]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],47:[2,136],52:[2,136],55:[2,136],70:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:85,101:[1,63],102:[2,136],103:[1,64],106:86,107:[1,66],108:67,115:[2,136],123:[2,136],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],47:[2,138],52:[2,138],55:[2,138],70:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],100:85,101:[1,63],102:[2,138],103:[1,64],106:86,107:[1,66],108:67,115:[2,138],123:[2,138],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{113:[2,156],114:[2,156]},{8:295,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],38:[2,85],47:[2,85],52:[2,85],55:[2,85],64:[2,85],65:[2,85],66:[2,85],68:[2,85],70:[2,85],71:[2,85],75:[2,85],81:[2,85],82:[2,85],83:[2,85],88:[2,85],90:[2,85],99:[2,85],101:[2,85],102:[2,85],103:[2,85],107:[2,85],113:[2,85],114:[2,85],115:[2,85],123:[2,85],125:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85]},{11:165,27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:298,40:164,42:168,44:[1,46],86:[1,111]},{6:[2,86],11:165,25:[2,86],26:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:299,86:[1,111]},{6:[2,88],25:[2,88],26:[2,88],52:[2,88],75:[2,88]},{6:[2,38],25:[2,38],26:[2,38],52:[2,38],75:[2,38],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:300,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,115],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],47:[2,36],52:[2,36],55:[2,36],70:[2,36],75:[2,36],83:[2,36],88:[2,36],90:[2,36],99:[2,36],101:[2,36],102:[2,36],103:[2,36],107:[2,36],115:[2,36],123:[2,36],125:[2,36],126:[2,36],129:[2,36],130:[2,36],131:[2,36],132:[2,36],133:[2,36],134:[2,36]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],47:[2,106],52:[2,106],55:[2,106],64:[2,106],65:[2,106],66:[2,106],68:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],47:[2,47],52:[2,47],55:[2,47],70:[2,47],75:[2,47],83:[2,47],88:[2,47],90:[2,47],99:[2,47],101:[2,47],102:[2,47],103:[2,47],107:[2,47],115:[2,47],123:[2,47],125:[2,47],126:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],133:[2,47],134:[2,47]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],47:[2,194],52:[2,194],55:[2,194],70:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],101:[2,194],102:[2,194],103:[2,194],107:[2,194],115:[2,194],123:[2,194],125:[2,194],126:[2,194],129:[2,194],130:[2,194],131:[2,194],132:[2,194],133:[2,194],134:[2,194]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],47:[2,173],52:[2,173],55:[2,173],70:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[2,173],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],47:[2,130],52:[2,130],55:[2,130],70:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{1:[2,131],6:[2,131],25:[2,131],26:[2,131],47:[2,131],52:[2,131],55:[2,131],70:[2,131],75:[2,131],83:[2,131],88:[2,131],90:[2,131],95:[2,131],99:[2,131],101:[2,131],102:[2,131],103:[2,131],107:[2,131],115:[2,131],123:[2,131],125:[2,131],126:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],133:[2,131],134:[2,131]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],47:[2,164],52:[2,164],55:[2,164],70:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],101:[2,164],102:[2,164],103:[2,164],107:[2,164],115:[2,164],123:[2,164],125:[2,164],126:[2,164],129:[2,164],130:[2,164],131:[2,164],132:[2,164],133:[2,164],134:[2,164]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,170],118:[2,170],120:[2,170]},{8:304,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],47:[2,98],52:[2,98],55:[2,98],70:[2,98],75:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],47:[2,134],52:[2,134],55:[2,134],64:[2,134],65:[2,134],66:[2,134],68:[2,134],70:[2,134],71:[2,134],75:[2,134],81:[2,134],82:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],101:[2,134],102:[2,134],103:[2,134],107:[2,134],115:[2,134],123:[2,134],125:[2,134],126:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],47:[2,114],52:[2,114],55:[2,114],64:[2,114],65:[2,114],66:[2,114],68:[2,114],70:[2,114],71:[2,114],75:[2,114],81:[2,114],82:[2,114],83:[2,114],88:[2,114],90:[2,114],99:[2,114],101:[2,114],102:[2,114],103:[2,114],107:[2,114],115:[2,114],123:[2,114],125:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114]},{6:[2,120],25:[2,120],26:[2,120],52:[2,120],83:[2,120],88:[2,120]},{6:[2,51],25:[2,51],26:[2,51],51:305,52:[1,222]},{6:[2,121],25:[2,121],26:[2,121],52:[2,121],83:[2,121],88:[2,121]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],47:[2,159],52:[2,159],55:[2,159],70:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:85,101:[2,159],102:[2,159],103:[2,159],106:86,107:[2,159],108:67,115:[1,306],123:[2,159],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],47:[2,161],52:[2,161],55:[2,161],70:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:85,101:[2,161],102:[1,307],103:[2,161],106:86,107:[2,161],108:67,115:[2,161],123:[2,161],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],47:[2,160],52:[2,160],55:[2,160],70:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:85,101:[2,160],102:[2,160],103:[2,160],106:86,107:[2,160],108:67,115:[2,160],123:[2,160],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,89],25:[2,89],26:[2,89],52:[2,89],75:[2,89]},{6:[2,51],25:[2,51],26:[2,51],51:308,52:[1,232]},{26:[1,309],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,310]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],47:[2,167],52:[2,167],55:[2,167],70:[2,167],75:[2,167],83:[2,167],88:[2,167],90:[2,167],99:[2,167],101:[2,167],102:[2,167],103:[2,167],107:[2,167],115:[2,167],123:[2,167],125:[2,167],126:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],133:[2,167],134:[2,167]},{26:[2,171],118:[2,171],120:[2,171]},{25:[2,126],52:[2,126],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,39],25:[2,39],26:[2,39],52:[2,39],75:[2,39]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],47:[2,165],52:[2,165],55:[2,165],70:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{6:[2,122],25:[2,122],26:[2,122],52:[2,122],83:[2,122],88:[2,122]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],47:[2,162],52:[2,162],55:[2,162],70:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:85,101:[2,162],102:[2,162],103:[2,162],106:86,107:[2,162],108:67,115:[2,162],123:[2,162],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],47:[2,163],52:[2,163],55:[2,163],70:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],100:85,101:[2,163],102:[2,163],103:[2,163],106:86,107:[2,163],108:67,115:[2,163],123:[2,163],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,90],25:[2,90],26:[2,90],52:[2,90],75:[2,90]}],
+defaultActions: {58:[2,49],59:[2,50],73:[2,3],92:[2,104],186:[2,84]},
+parseError: function parseError(str, hash) {
+    throw new Error(str);
+},
+parse: function parse(input) {
+    var self = this,
+        stack = [0],
+        vstack = [null], // semantic value stack
+        lstack = [], // location stack
+        table = this.table,
+        yytext = '',
+        yylineno = 0,
+        yyleng = 0,
+        recovering = 0,
+        TERROR = 2,
+        EOF = 1;
+
+    //this.reductionCount = this.shiftCount = 0;
+
+    this.lexer.setInput(input);
+    this.lexer.yy = this.yy;
+    this.yy.lexer = this.lexer;
+    if (typeof this.lexer.yylloc == 'undefined')
+        this.lexer.yylloc = {};
+    var yyloc = this.lexer.yylloc;
+    lstack.push(yyloc);
+
+    if (typeof this.yy.parseError === 'function')
+        this.parseError = this.yy.parseError;
+
+    function popStack (n) {
+        stack.length = stack.length - 2*n;
+        vstack.length = vstack.length - n;
+        lstack.length = lstack.length - n;
+    }
+
+    function lex() {
+        var token;
+        token = self.lexer.lex() || 1; // $end = 1
+        // if token isn't its numeric value, convert
+        if (typeof token !== 'number') {
+            token = self.symbols_[token] || token;
+        }
+        return token;
+    };
+
+    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
+    while (true) {
+        // retreive state number from top of stack
+        state = stack[stack.length-1];
+
+        // use default actions if available
+        if (this.defaultActions[state]) {
+            action = this.defaultActions[state];
+        } else {
+            if (symbol == null)
+                symbol = lex();
+            // read action for current state and first input
+            action = table[state] && table[state][symbol];
+        }
+
+        // handle parse error
+        if (typeof action === 'undefined' || !action.length || !action[0]) {
+
+            if (!recovering) {
+                // Report error
+                expected = [];
+                for (p in table[state]) if (this.terminals_[p] && p > 2) {
+                    expected.push("'"+this.terminals_[p]+"'");
+                }
+                var errStr = '';
+                if (this.lexer.showPosition) {
+                    errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', ');
+                } else {
+                    errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
+                                  (symbol == 1 /*EOF*/ ? "end of input" :
+                                              ("'"+(this.terminals_[symbol] || symbol)+"'"));
+                }
+                this.parseError(errStr,
+                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
+            }
+
+            // just recovered from another error
+            if (recovering == 3) {
+                if (symbol == EOF) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+
+                // discard current lookahead and grab another
+                yyleng = this.lexer.yyleng;
+                yytext = this.lexer.yytext;
+                yylineno = this.lexer.yylineno;
+                yyloc = this.lexer.yylloc;
+                symbol = lex();
+            }
+
+            // try to recover from error
+            while (1) {
+                // check for error recovery rule in this state
+                if ((TERROR.toString()) in table[state]) {
+                    break;
+                }
+                if (state == 0) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+                popStack(1);
+                state = stack[stack.length-1];
+            }
+
+            preErrorSymbol = symbol; // save the lookahead token
+            symbol = TERROR;         // insert generic error symbol as new lookahead
+            state = stack[stack.length-1];
+            action = table[state] && table[state][TERROR];
+            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
+        }
+
+        // this shouldn't happen, unless resolve defaults are off
+        if (action[0] instanceof Array && action.length > 1) {
+            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
+        }
+
+        switch (action[0]) {
+
+            case 1: // shift
+                //this.shiftCount++;
+
+                stack.push(symbol);
+                vstack.push(this.lexer.yytext);
+                lstack.push(this.lexer.yylloc);
+                stack.push(action[1]); // push state
+                symbol = null;
+                if (!preErrorSymbol) { // normal execution/no error
+                    yyleng = this.lexer.yyleng;
+                    yytext = this.lexer.yytext;
+                    yylineno = this.lexer.yylineno;
+                    yyloc = this.lexer.yylloc;
+                    if (recovering > 0)
+                        recovering--;
+                } else { // error just occurred, resume old lookahead f/ before error
+                    symbol = preErrorSymbol;
+                    preErrorSymbol = null;
+                }
+                break;
+
+            case 2: // reduce
+                //this.reductionCount++;
+
+                len = this.productions_[action[1]][1];
+
+                // perform semantic action
+                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
+                // default location, uses first token for firsts, last for lasts
+                yyval._$ = {
+                    first_line: lstack[lstack.length-(len||1)].first_line,
+                    last_line: lstack[lstack.length-1].last_line,
+                    first_column: lstack[lstack.length-(len||1)].first_column,
+                    last_column: lstack[lstack.length-1].last_column
+                };
+                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+
+                if (typeof r !== 'undefined') {
+                    return r;
+                }
+
+                // pop off stack
+                if (len) {
+                    stack = stack.slice(0,-1*len*2);
+                    vstack = vstack.slice(0, -1*len);
+                    lstack = lstack.slice(0, -1*len);
+                }
+
+                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)
+                vstack.push(yyval.$);
+                lstack.push(yyval._$);
+                // goto new state = table[STATE][NONTERMINAL]
+                newState = table[stack[stack.length-2]][stack[stack.length-1]];
+                stack.push(newState);
+                break;
+
+            case 3: // accept
+                return true;
+        }
+
+    }
+
+    return true;
+}};
+return parser;
+})();
+if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
+exports.parser = parser;
+exports.parse = function () { return parser.parse.apply(parser, arguments); }
+exports.main = function commonjsMain(args) {
+    if (!args[1])
+        throw new Error('Usage: '+args[0]+' FILE');
+    if (typeof process !== 'undefined') {
+        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
+    } else {
+        var cwd = require("file").path(require("file").cwd());
+        var source = cwd.join(args[1]).read({charset: "utf-8"});
+    }
+    return exports.parser.parse(source);
+}
+if (typeof module !== 'undefined' && require.main === module) {
+  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
+}
+}
\ No newline at end of file
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/repl.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/repl.js
new file mode 100644
index 0000000..3368d7c
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/repl.js
@@ -0,0 +1,149 @@
+(function() {
+  var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, readline, repl, run, stdin, stdout;
+
+  CoffeeScript = require('./coffee-script');
+
+  readline = require('readline');
+
+  inspect = require('util').inspect;
+
+  Script = require('vm').Script;
+
+  Module = require('module');
+
+  REPL_PROMPT = 'coffee> ';
+
+  REPL_PROMPT_CONTINUATION = '......> ';
+
+  enableColours = false;
+
+  if (process.platform !== 'win32') {
+    enableColours = !process.env.NODE_DISABLE_COLORS;
+  }
+
+  stdin = process.openStdin();
+
+  stdout = process.stdout;
+
+  error = function(err) {
+    return stdout.write((err.stack || err.toString()) + '\n');
+  };
+
+  backlog = '';
+
+  run = function(buffer) {
+    var code, returnValue, _;
+    if (!buffer.toString().trim() && !backlog) {
+      repl.prompt();
+      return;
+    }
+    code = backlog += buffer;
+    if (code[code.length - 1] === '\\') {
+      backlog = "" + backlog.slice(0, -1) + "\n";
+      repl.setPrompt(REPL_PROMPT_CONTINUATION);
+      repl.prompt();
+      return;
+    }
+    repl.setPrompt(REPL_PROMPT);
+    backlog = '';
+    try {
+      _ = global._;
+      returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
+        filename: 'repl',
+        modulename: 'repl'
+      });
+      if (returnValue === void 0) global._ = _;
+      process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
+    } catch (err) {
+      error(err);
+    }
+    return repl.prompt();
+  };
+
+  ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
+
+  SIMPLEVAR = /\s*(\w*)$/i;
+
+  autocomplete = function(text) {
+    return completeAttribute(text) || completeVariable(text) || [[], text];
+  };
+
+  completeAttribute = function(text) {
+    var all, completions, match, obj, prefix, val;
+    if (match = text.match(ACCESSOR)) {
+      all = match[0], obj = match[1], prefix = match[2];
+      try {
+        val = Script.runInThisContext(obj);
+      } catch (error) {
+        return;
+      }
+      completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
+      return [completions, prefix];
+    }
+  };
+
+  completeVariable = function(text) {
+    var completions, free, keywords, possibilities, r, vars, _ref;
+    free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
+    if (free != null) {
+      vars = Script.runInThisContext('Object.getOwnPropertyNames(this)');
+      keywords = (function() {
+        var _i, _len, _ref2, _results;
+        _ref2 = CoffeeScript.RESERVED;
+        _results = [];
+        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+          r = _ref2[_i];
+          if (r.slice(0, 2) !== '__') _results.push(r);
+        }
+        return _results;
+      })();
+      possibilities = vars.concat(keywords);
+      completions = getCompletions(free, possibilities);
+      return [completions, free];
+    }
+  };
+
+  getCompletions = function(prefix, candidates) {
+    var el, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = candidates.length; _i < _len; _i++) {
+      el = candidates[_i];
+      if (el.indexOf(prefix) === 0) _results.push(el);
+    }
+    return _results;
+  };
+
+  process.on('uncaughtException', error);
+
+  if (readline.createInterface.length < 3) {
+    repl = readline.createInterface(stdin, autocomplete);
+    stdin.on('data', function(buffer) {
+      return repl.write(buffer);
+    });
+  } else {
+    repl = readline.createInterface(stdin, stdout, autocomplete);
+  }
+
+  repl.on('attemptClose', function() {
+    if (backlog) {
+      backlog = '';
+      process.stdout.write('\n');
+      repl.setPrompt(REPL_PROMPT);
+      return repl.prompt();
+    } else {
+      return repl.close();
+    }
+  });
+
+  repl.on('close', function() {
+    process.stdout.write('\n');
+    return stdin.destroy();
+  });
+
+  repl.on('line', run);
+
+  repl.setPrompt(REPL_PROMPT);
+
+  repl.prompt();
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/rewriter.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/rewriter.js
new file mode 100644
index 0000000..b4fdc07
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/rewriter.js
@@ -0,0 +1,301 @@
+(function() {
+  var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,
+    __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+    __slice = Array.prototype.slice;
+
+  exports.Rewriter = (function() {
+
+    function Rewriter() {}
+
+    Rewriter.prototype.rewrite = function(tokens) {
+      this.tokens = tokens;
+      this.removeLeadingNewlines();
+      this.removeMidExpressionNewlines();
+      this.closeOpenCalls();
+      this.closeOpenIndexes();
+      this.addImplicitIndentation();
+      this.tagPostfixConditionals();
+      this.addImplicitBraces();
+      this.addImplicitParentheses();
+      return this.tokens;
+    };
+
+    Rewriter.prototype.scanTokens = function(block) {
+      var i, token, tokens;
+      tokens = this.tokens;
+      i = 0;
+      while (token = tokens[i]) {
+        i += block.call(this, token, i, tokens);
+      }
+      return true;
+    };
+
+    Rewriter.prototype.detectEnd = function(i, condition, action) {
+      var levels, token, tokens, _ref, _ref2;
+      tokens = this.tokens;
+      levels = 0;
+      while (token = tokens[i]) {
+        if (levels === 0 && condition.call(this, token, i)) {
+          return action.call(this, token, i);
+        }
+        if (!token || levels < 0) return action.call(this, token, i - 1);
+        if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
+          levels += 1;
+        } else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
+          levels -= 1;
+        }
+        i += 1;
+      }
+      return i - 1;
+    };
+
+    Rewriter.prototype.removeLeadingNewlines = function() {
+      var i, tag, _len, _ref;
+      _ref = this.tokens;
+      for (i = 0, _len = _ref.length; i < _len; i++) {
+        tag = _ref[i][0];
+        if (tag !== 'TERMINATOR') break;
+      }
+      if (i) return this.tokens.splice(0, i);
+    };
+
+    Rewriter.prototype.removeMidExpressionNewlines = function() {
+      return this.scanTokens(function(token, i, tokens) {
+        var _ref;
+        if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
+          return 1;
+        }
+        tokens.splice(i, 1);
+        return 0;
+      });
+    };
+
+    Rewriter.prototype.closeOpenCalls = function() {
+      var action, condition;
+      condition = function(token, i) {
+        var _ref;
+        return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
+      };
+      action = function(token, i) {
+        return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
+        return 1;
+      });
+    };
+
+    Rewriter.prototype.closeOpenIndexes = function() {
+      var action, condition;
+      condition = function(token, i) {
+        var _ref;
+        return (_ref = token[0]) === ']' || _ref === 'INDEX_END';
+      };
+      action = function(token, i) {
+        return token[0] = 'INDEX_END';
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
+        return 1;
+      });
+    };
+
+    Rewriter.prototype.addImplicitBraces = function() {
+      var action, condition, sameLine, stack, start, startIndent, startsLine;
+      stack = [];
+      start = null;
+      startsLine = null;
+      sameLine = true;
+      startIndent = 0;
+      condition = function(token, i) {
+        var one, tag, three, two, _ref, _ref2;
+        _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
+        if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
+        tag = token[0];
+        if (__indexOf.call(LINEBREAKS, tag) >= 0) sameLine = false;
+        return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine)) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
+      };
+      action = function(token, i) {
+        var tok;
+        tok = ['}', '}', token[2]];
+        tok.generated = true;
+        return this.tokens.splice(i, 0, tok);
+      };
+      return this.scanTokens(function(token, i, tokens) {
+        var ago, idx, prevTag, tag, tok, value, _ref, _ref2;
+        if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
+          stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
+          return 1;
+        }
+        if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
+          start = stack.pop();
+          return 1;
+        }
+        if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
+          return 1;
+        }
+        sameLine = true;
+        stack.push(['{']);
+        idx = ago === '@' ? i - 2 : i - 1;
+        while (this.tag(idx - 2) === 'HERECOMMENT') {
+          idx -= 2;
+        }
+        prevTag = this.tag(idx - 1);
+        startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
+        value = new String('{');
+        value.generated = true;
+        tok = ['{', value, token[2]];
+        tok.generated = true;
+        tokens.splice(idx, 0, tok);
+        this.detectEnd(i + 2, condition, action);
+        return 2;
+      });
+    };
+
+    Rewriter.prototype.addImplicitParentheses = function() {
+      var action, condition, noCall, seenControl, seenSingle;
+      noCall = seenSingle = seenControl = false;
+      condition = function(token, i) {
+        var post, tag, _ref, _ref2;
+        tag = token[0];
+        if (!seenSingle && token.fromThen) return true;
+        if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
+          seenSingle = true;
+        }
+        if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
+          seenControl = true;
+        }
+        if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
+          return true;
+        }
+        return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref2 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref2) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
+      };
+      action = function(token, i) {
+        return this.tokens.splice(i, 0, ['CALL_END', ')', token[2]]);
+      };
+      return this.scanTokens(function(token, i, tokens) {
+        var callObject, current, next, prev, tag, _ref, _ref2, _ref3;
+        tag = token[0];
+        if (tag === 'CLASS' || tag === 'IF') noCall = true;
+        _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
+        callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
+        seenSingle = false;
+        seenControl = false;
+        if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
+        if (prev && !prev.spaced && tag === '?') token.call = true;
+        if (token.fromThen) return 1;
+        if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
+          return 1;
+        }
+        tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
+        this.detectEnd(i + 1, condition, action);
+        if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
+        return 2;
+      });
+    };
+
+    Rewriter.prototype.addImplicitIndentation = function() {
+      var action, condition, indent, outdent, starter;
+      starter = indent = outdent = null;
+      condition = function(token, i) {
+        var _ref;
+        return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
+      };
+      action = function(token, i) {
+        return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
+      };
+      return this.scanTokens(function(token, i, tokens) {
+        var tag, _ref, _ref2;
+        tag = token[0];
+        if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
+          tokens.splice(i, 1);
+          return 0;
+        }
+        if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
+          tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));
+          return 2;
+        }
+        if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
+          tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));
+          return 4;
+        }
+        if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
+          starter = tag;
+          _ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
+          if (starter === 'THEN') indent.fromThen = true;
+          indent.generated = outdent.generated = true;
+          tokens.splice(i + 1, 0, indent);
+          this.detectEnd(i + 2, condition, action);
+          if (tag === 'THEN') tokens.splice(i, 1);
+          return 1;
+        }
+        return 1;
+      });
+    };
+
+    Rewriter.prototype.tagPostfixConditionals = function() {
+      var action, condition, original;
+      original = null;
+      condition = function(token, i) {
+        var _ref;
+        return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
+      };
+      action = function(token, i) {
+        if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
+          return original[0] = 'POST_' + original[0];
+        }
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] !== 'IF') return 1;
+        original = token;
+        this.detectEnd(i + 1, condition, action);
+        return 1;
+      });
+    };
+
+    Rewriter.prototype.indentation = function(token) {
+      return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
+    };
+
+    Rewriter.prototype.tag = function(i) {
+      var _ref;
+      return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
+    };
+
+    return Rewriter;
+
+  })();
+
+  BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
+
+  exports.INVERSES = INVERSES = {};
+
+  EXPRESSION_START = [];
+
+  EXPRESSION_END = [];
+
+  for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
+    _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
+    EXPRESSION_START.push(INVERSES[rite] = left);
+    EXPRESSION_END.push(INVERSES[left] = rite);
+  }
+
+  EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
+
+  IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
+
+  IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
+
+  IMPLICIT_UNSPACED_CALL = ['+', '-'];
+
+  IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
+
+  IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
+
+  SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
+
+  SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
+
+  LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
+
+}).call(this);
diff --git a/weinre.server/node_modules/coffee-script/lib/coffee-script/scope.js b/weinre.server/node_modules/coffee-script/lib/coffee-script/scope.js
new file mode 100644
index 0000000..2162853
--- /dev/null
+++ b/weinre.server/node_modules/coffee-script/lib/coffee-script/scope.js
@@ -0,0 +1,124 @@
+(function() {
+  var Scope, extend, last, _ref;
+
+  _ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
+
+  exports.Scope = Scope = (function() {
+
+    Scope.root = null;
+
+    function Scope(parent, expressions, method) {
+      this.parent = parent;
+      this.expressions = expressions;
+      this.method = method;
+      this.variables = [
+        {
+          name: 'arguments',
+          type: 'arguments'
+        }
+      ];
+      this.positions = {};
+      if (!this.parent) Scope.root = this;
+    }
+
+    Scope.prototype.add = function(name, type, immediate) {
+      if (this.shared && !immediate) return this.parent.add(name, type, immediate);
+      if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
+        return this.variables[this.positions[name]].type = type;
+      } else {
+        return this.positions[name] = this.variables.push({
+          name: name,
+          type: type
+        }) - 1;
+      }
+    };
+
+    Scope.prototype.find = function(name, options) {
+      if (this.check(name, options)) return true;
+      this.add(name, 'var');
+      return false;
+    };
+
+    Scope.prototype.parameter = function(name) {
+      if (this.shared && this.parent.check(name, true)) return;
+      return this.add(name, 'param');
+    };
+
+    Scope.prototype.check = function(name, immediate) {
+      var found, _ref2;
+      found = !!this.type(name);
+      if (found || immediate) return found;
+      return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
+    };
+
+    Scope.prototype.temporary = function(name, index) {
+      if (name.length > 1) {
+        return '_' + name + (index > 1 ? index : '');
+      } else {
+        return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
+      }
+    };
+
+    Scope.prototype.type = function(name) {
+      var v, _i, _len, _ref2;
+      _ref2 = this.variables;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.name === name) return v.type;
+      }
+      return null;
+    };
+
+    Scope.prototype.freeVariable = function(name, reserve) {
+      var index, temp;
+      if (reserve == null) reserve = true;
+      index = 0;
+      while (this.check((temp = this.temporary(name, index)))) {
+        index++;
+      }
+      if (reserve) this.add(temp, 'var', true);
+      return temp;
+    };
+
+    Scope.prototype.assign = function(name, value) {
+      this.add(name, {
+        value: value,
+        assigned: true
+      }, true);
+      return this.hasAssignments = true;
+    };
+
+    Scope.prototype.hasDeclarations = function() {
+      return !!this.declaredVariables().length;
+    };
+
+    Scope.prototype.declaredVariables = function() {
+      var realVars, tempVars, v, _i, _len, _ref2;
+      realVars = [];
+      tempVars = [];
+      _ref2 = this.variables;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.type === 'var') {
+          (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
+        }
+      }
+      return realVars.sort().concat(tempVars.sort());
+    };
+
+    Scope.prototype.assignedVariables = function() {
+      var v, _i, _len, _ref2, _results;
+      _ref2 = this.variables;
+      _results = [];
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        v = _ref2[_i];
+        if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
+      }
+      return _results;
+    };
+
+    return Scope;
+
+  })();
+
+}).call(this);
diff --git a/weinre.server/node_modules/express/.npmignore b/weinre.server/node_modules/express/.npmignore
new file mode 100644
index 0000000..74bd365
--- /dev/null
+++ b/weinre.server/node_modules/express/.npmignore
@@ -0,0 +1,7 @@
+.git*
+docs/
+examples/
+support/
+test/
+testing.js
+.DS_Store
diff --git a/weinre.server/node_modules/express/History.md b/weinre.server/node_modules/express/History.md
new file mode 100644
index 0000000..616ca9d
--- /dev/null
+++ b/weinre.server/node_modules/express/History.md
@@ -0,0 +1,800 @@
+
+2.5.7 / 2012-02-06 
+==================
+
+  * Fixed `app.all` duplicate DELETE requests [mscdex]
+
+2.5.6 / 2012-01-13 
+==================
+
+  * Updated hamljs dev dep. Closes #953
+
+2.5.5 / 2012-01-08 
+==================
+
+  * Fixed: set `filename` on cached templates [matthewleon]
+
+2.5.4 / 2012-01-02 
+==================
+
+  * Fixed `express(1)` eol on 0.4.x. Closes #947
+
+2.5.3 / 2011-12-30 
+==================
+
+  * Fixed `req.is()` when a charset is present
+
+2.5.2 / 2011-12-10 
+==================
+
+  * Fixed: express(1) LF -> CRLF for windows
+
+2.5.1 / 2011-11-17 
+==================
+
+  * Changed: updated connect to 1.8.x
+  * Removed sass.js support from express(1)
+
+2.5.0 / 2011-10-24 
+==================
+
+  * Added ./routes dir for generated app by default
+  * Added npm install reminder to express(1) app gen
+  * Added 0.5.x support
+  * Removed `make test-cov` since it wont work with node 0.5.x
+  * Fixed express(1) public dir for windows. Closes #866
+
+2.4.7 / 2011-10-05 
+==================
+
+  * Added mkdirp to express(1). Closes #795
+  * Added simple _json-config_ example
+  * Added  shorthand for the parsed request's pathname via `req.path`
+  * Changed connect dep to 1.7.x to fix npm issue...
+  * Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
+  * Fixed `req.flash()`, only escape args
+  * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
+
+2.4.6 / 2011-08-22 
+==================
+
+  * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
+
+2.4.5 / 2011-08-19 
+==================
+
+  * Added support for routes to handle errors. Closes #809
+  * Added `app.routes.all()`. Closes #803
+  * Added "basepath" setting to work in conjunction with reverse proxies etc.   
+  * Refactored `Route` to use a single array of callbacks
+  * Added support for multiple callbacks for `app.param()`. Closes #801
+Closes #805
+  * Changed: removed .call(self) for route callbacks
+  * Dependency: `qs >= 0.3.1`
+  * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
+
+2.4.4 / 2011-08-05 
+==================
+
+  * Fixed `res.header()` intention of a set, even when `undefined`
+  * Fixed `*`, value no longer required
+  * Fixed `res.send(204)` support. Closes #771
+
+2.4.3 / 2011-07-14 
+==================
+
+  * Added docs for `status` option special-case. Closes #739
+  * Fixed `options.filename`, exposing the view path to template engines
+
+2.4.2. / 2011-07-06 
+==================
+
+  * Revert "removed jsonp stripping" for XSS
+
+2.4.1 / 2011-07-06 
+==================
+
+  * Added `res.json()` JSONP support. Closes #737
+  * Added _extending-templates_ example. Closes #730
+  * Added "strict routing" setting for trailing slashes
+  * Added support for multiple envs in `app.configure()` calls. Closes #735
+  * Changed: `res.send()` using `res.json()`
+  * Changed: when cookie `path === null` don't default it
+  * Changed; default cookie path to "home" setting. Closes #731
+  * Removed _pids/logs_ creation from express(1)
+
+2.4.0 / 2011-06-28 
+==================
+
+  * Added chainable `res.status(code)`
+  * Added `res.json()`, an explicit version of `res.send(obj)`
+  * Added simple web-service example
+
+2.3.12 / 2011-06-22 
+==================
+
+  * \#express is now on freenode! come join!
+  * Added `req.get(field, param)`
+  * Added links to Japanese documentation, thanks @hideyukisaito!
+  * Added; the `express(1)` generated app outputs the env
+  * Added `content-negotiation` example
+  * Dependency: connect >= 1.5.1 < 2.0.0
+  * Fixed view layout bug. Closes #720
+  * Fixed; ignore body on 304. Closes #701
+
+2.3.11 / 2011-06-04 
+==================
+
+  * Added `npm test`
+  * Removed generation of dummy test file from `express(1)`
+  * Fixed; `express(1)` adds express as a dep
+  * Fixed; prune on `prepublish`
+
+2.3.10 / 2011-05-27 
+==================
+
+  * Added `req.route`, exposing the current route
+  * Added _package.json_ generation support to `express(1)`
+  * Fixed call to `app.param()` function for optional params. Closes #682
+
+2.3.9 / 2011-05-25 
+==================
+
+  * Fixed bug-ish with `../' in `res.partial()` calls
+
+2.3.8 / 2011-05-24
+==================
+
+  * Fixed `app.options()`
+
+2.3.7 / 2011-05-23
+==================
+
+  * Added route `Collection`, ex: `app.get('/user/:id').remove();`
+  * Added support for `app.param(fn)` to define param logic
+  * Removed `app.param()` support for callback with return value
+  * Removed module.parent check from express(1) generated app. Closes #670
+  * Refactored router. Closes #639
+
+2.3.6 / 2011-05-20 
+==================
+
+  * Changed; using devDependencies instead of git submodules
+  * Fixed redis session example
+  * Fixed markdown example
+  * Fixed view caching, should not be enabled in development
+
+2.3.5 / 2011-05-20 
+==================
+
+  * Added export `.view` as alias for `.View`
+
+2.3.4 / 2011-05-08 
+==================
+
+  * Added `./examples/say`
+  * Fixed `res.sendfile()` bug preventing the transfer of files with spaces
+
+2.3.3 / 2011-05-03 
+==================
+
+  * Added "case sensitive routes" option.
+  * Changed; split methods supported per rfc [slaskis]
+  * Fixed route-specific middleware when using the same callback function several times
+
+2.3.2 / 2011-04-27 
+==================
+
+  * Fixed view hints
+
+2.3.1 / 2011-04-26 
+==================
+
+  * Added `app.match()` as `app.match.all()`
+  * Added `app.lookup()` as `app.lookup.all()`
+  * Added `app.remove()` for `app.remove.all()`
+  * Added `app.remove.VERB()`
+  * Fixed template caching collision issue. Closes #644
+  * Moved router over from connect and started refactor
+
+2.3.0 / 2011-04-25 
+==================
+
+  * Added options support to `res.clearCookie()`
+  * Added `res.helpers()` as alias of `res.locals()`
+  * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel   * Dependency `connect >= 1.4.0`
+  * Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
+  * Renamed "cache views" to "view cache". Closes #628
+  * Fixed caching of views when using several apps. Closes #637
+  * Fixed gotcha invoking `app.param()` callbacks once per route middleware. 
+Closes #638
+  * Fixed partial lookup precedence. Closes #631
+Shaw]
+
+2.2.2 / 2011-04-12 
+==================
+
+  * Added second callback support for `res.download()` connection errors
+  * Fixed `filename` option passing to template engine
+
+2.2.1 / 2011-04-04 
+==================
+
+  * Added `layout(path)` helper to change the layout within a view. Closes #610
+  * Fixed `partial()` collection object support.
+    Previously only anything with `.length` would work.
+    When `.length` is present one must still be aware of holes,
+    however now `{ collection: {foo: 'bar'}}` is valid, exposes
+    `keyInCollection` and `keysInCollection`.
+
+  * Performance improved with better view caching
+  * Removed `request` and `response` locals
+  * Changed; errorHandler page title is now `Express` instead of `Connect`
+
+2.2.0 / 2011-03-30 
+==================
+
+  * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
+  * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
+  * Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
+  * Dependency `connect >= 1.2.0`
+
+2.1.1 / 2011-03-29 
+==================
+
+  * Added; expose `err.view` object when failing to locate a view
+  * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
+  * Fixed; `res.send(undefined)` responds with 204 [aheckmann]
+
+2.1.0 / 2011-03-24 
+==================
+
+  * Added `<root>/_?<name>` partial lookup support. Closes #447
+  * Added `request`, `response`, and `app` local variables
+  * Added `settings` local variable, containing the app's settings
+  * Added `req.flash()` exception if `req.session` is not available
+  * Added `res.send(bool)` support (json response)
+  * Fixed stylus example for latest version
+  * Fixed; wrap try/catch around `res.render()`
+
+2.0.0 / 2011-03-17 
+==================
+
+  * Fixed up index view path alternative.
+  * Changed; `res.locals()` without object returns the locals
+
+2.0.0rc3 / 2011-03-17 
+==================
+
+  * Added `res.locals(obj)` to compliment `res.local(key, val)`
+  * Added `res.partial()` callback support
+  * Fixed recursive error reporting issue in `res.render()`
+
+2.0.0rc2 / 2011-03-17 
+==================
+
+  * Changed; `partial()` "locals" are now optional
+  * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
+  * Fixed .filename view engine option [reported by drudge]
+  * Fixed blog example
+  * Fixed `{req,res}.app` reference when mounting [Ben Weaver]
+
+2.0.0rc / 2011-03-14 
+==================
+
+  * Fixed; expose `HTTPSServer` constructor
+  * Fixed express(1) default test charset. Closes #579 [reported by secoif]
+  * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]
+
+2.0.0beta3 / 2011-03-09 
+==================
+
+  * Added support for `res.contentType()` literal
+    The original `res.contentType('.json')`,
+    `res.contentType('application/json')`, and `res.contentType('json')`
+    will work now.
+  * Added `res.render()` status option support back
+  * Added charset option for `res.render()`
+  * Added `.charset` support (via connect 1.0.4)
+  * Added view resolution hints when in development and a lookup fails
+  * Added layout lookup support relative to the page view.
+    For example while rendering `./views/user/index.jade` if you create
+    `./views/user/layout.jade` it will be used in favour of the root layout.
+  * Fixed `res.redirect()`. RFC states absolute url [reported by unlink]
+  * Fixed; default `res.send()` string charset to utf8
+  * Removed `Partial` constructor (not currently used)
+
+2.0.0beta2 / 2011-03-07 
+==================
+
+  * Added res.render() `.locals` support back to aid in migration process
+  * Fixed flash example
+
+2.0.0beta / 2011-03-03 
+==================
+
+  * Added HTTPS support
+  * Added `res.cookie()` maxAge support
+  * Added `req.header()` _Referrer_ / _Referer_ special-case, either works
+  * Added mount support for `res.redirect()`, now respects the mount-point
+  * Added `union()` util, taking place of `merge(clone())` combo
+  * Added stylus support to express(1) generated app
+  * Added secret to session middleware used in examples and generated app
+  * Added `res.local(name, val)` for progressive view locals
+  * Added default param support to `req.param(name, default)`
+  * Added `app.disabled()` and `app.enabled()`
+  * Added `app.register()` support for omitting leading ".", either works
+  * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539
+  * Added `app.param()` to map route params to async/sync logic
+  * Added; aliased `app.helpers()` as `app.locals()`. Closes #481
+  * Added extname with no leading "." support to `res.contentType()`
+  * Added `cache views` setting, defaulting to enabled in "production" env
+  * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_.
+  * Added `req.accepts()` support for extensions
+  * Changed; `res.download()` and `res.sendfile()` now utilize Connect's
+    static file server `connect.static.send()`.
+  * Changed; replaced `connect.utils.mime()` with npm _mime_ module
+  * Changed; allow `req.query` to be pre-defined (via middleware or other parent
+  * Changed view partial resolution, now relative to parent view
+  * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`.
+  * Fixed `req.param()` bug returning Array.prototype methods. Closes #552
+  * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()`
+  * Fixed; using _qs_ module instead of _querystring_
+  * Fixed; strip unsafe chars from jsonp callbacks
+  * Removed "stream threshold" setting
+
+1.0.8 / 2011-03-01 
+==================
+
+  * Allow `req.query` to be pre-defined (via middleware or other parent app)
+  * "connect": ">= 0.5.0 < 1.0.0". Closes #547
+  * Removed the long deprecated __EXPRESS_ENV__ support
+
+1.0.7 / 2011-02-07 
+==================
+
+  * Fixed `render()` setting inheritance.
+    Mounted apps would not inherit "view engine"
+
+1.0.6 / 2011-02-07 
+==================
+
+  * Fixed `view engine` setting bug when period is in dirname
+
+1.0.5 / 2011-02-05 
+==================
+
+  * Added secret to generated app `session()` call
+
+1.0.4 / 2011-02-05 
+==================
+
+  * Added `qs` dependency to _package.json_
+  * Fixed namespaced `require()`s for latest connect support
+
+1.0.3 / 2011-01-13 
+==================
+
+  * Remove unsafe characters from JSONP callback names [Ryan Grove]
+
+1.0.2 / 2011-01-10 
+==================
+
+  * Removed nested require, using `connect.router`
+
+1.0.1 / 2010-12-29 
+==================
+
+  * Fixed for middleware stacked via `createServer()`
+    previously the `foo` middleware passed to `createServer(foo)`
+    would not have access to Express methods such as `res.send()`
+    or props like `req.query` etc.
+
+1.0.0 / 2010-11-16 
+==================
+
+  * Added; deduce partial object names from the last segment.
+    For example by default `partial('forum/post', postObject)` will
+    give you the _post_ object, providing a meaningful default.
+  * Added http status code string representation to `res.redirect()` body
+  * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__.
+  * Added `req.is()` to aid in content negotiation
+  * Added partial local inheritance [suggested by masylum]. Closes #102
+    providing access to parent template locals.
+  * Added _-s, --session[s]_ flag to express(1) to add session related middleware
+  * Added _--template_ flag to express(1) to specify the
+    template engine to use.
+  * Added _--css_ flag to express(1) to specify the 
+    stylesheet engine to use (or just plain css by default).
+  * Added `app.all()` support [thanks aheckmann]
+  * Added partial direct object support.
+    You may now `partial('user', user)` providing the "user" local,
+    vs previously `partial('user', { object: user })`.
+  * Added _route-separation_ example since many people question ways
+    to do this with CommonJS modules. Also view the _blog_ example for
+    an alternative.
+  * Performance; caching view path derived partial object names
+  * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
+  * Fixed jsonp support; _text/javascript_ as per mailinglist discussion
+
+1.0.0rc4 / 2010-10-14 
+==================
+
+  * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0
+  * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware))
+  * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass]
+  * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass]
+  * Added `partial()` support for array-like collections. Closes #434
+  * Added support for swappable querystring parsers
+  * Added session usage docs. Closes #443
+  * Added dynamic helper caching. Closes #439 [suggested by maritz]
+  * Added authentication example
+  * Added basic Range support to `res.sendfile()` (and `res.download()` etc)
+  * Changed; `express(1)` generated app using 2 spaces instead of 4
+  * Default env to "development" again [aheckmann]
+  * Removed _context_ option is no more, use "scope"
+  * Fixed; exposing _./support_ libs to examples so they can run without installs
+  * Fixed mvc example
+
+1.0.0rc3 / 2010-09-20 
+==================
+
+  * Added confirmation for `express(1)` app generation. Closes #391
+  * Added extending of flash formatters via `app.flashFormatters`
+  * Added flash formatter support. Closes #411
+  * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold"
+  * Added _stream threshold_ setting for `res.sendfile()`
+  * Added `res.send()` __HEAD__ support
+  * Added `res.clearCookie()`
+  * Added `res.cookie()`
+  * Added `res.render()` headers option
+  * Added `res.redirect()` response bodies
+  * Added `res.render()` status option support. Closes #425 [thanks aheckmann]
+  * Fixed `res.sendfile()` responding with 403 on malicious path
+  * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_
+  * Fixed; mounted apps settings now inherit from parent app [aheckmann]
+  * Fixed; stripping Content-Length / Content-Type when 204
+  * Fixed `res.send()` 204. Closes #419
+  * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402
+  * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo]
+
+
+1.0.0rc2 / 2010-08-17 
+==================
+
+  * Added `app.register()` for template engine mapping. Closes #390
+  * Added `res.render()` callback support as second argument (no options)
+  * Added callback support to `res.download()`
+  * Added callback support for `res.sendfile()`
+  * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()`
+  * Added "partials" setting to docs
+  * Added default expresso tests to `express(1)` generated app. Closes #384
+  * Fixed `res.sendfile()` error handling, defer via `next()`
+  * Fixed `res.render()` callback when a layout is used [thanks guillermo]
+  * Fixed; `make install` creating ~/.node_libraries when not present
+  * Fixed issue preventing error handlers from being defined anywhere. Closes #387 
+
+1.0.0rc / 2010-07-28
+==================
+
+  * Added mounted hook. Closes #369
+  * Added connect dependency to _package.json_
+
+  * Removed "reload views" setting and support code
+    development env never caches, production always caches.
+
+  * Removed _param_ in route callbacks, signature is now
+    simply (req, res, next), previously (req, res, params, next).
+    Use _req.params_ for path captures, _req.query_ for GET params.
+
+  * Fixed "home" setting
+  * Fixed middleware/router precedence issue. Closes #366
+  * Fixed; _configure()_ callbacks called immediately. Closes #368
+	
+1.0.0beta2 / 2010-07-23
+==================
+
+  * Added more examples
+  * Added; exporting `Server` constructor
+  * Added `Server#helpers()` for view locals
+  * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349
+  * Added support for absolute view paths
+  * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363
+  * Added Guillermo Rauch to the contributor list
+  * Added support for "as" for non-collection partials. Closes #341
+  * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf]
+  * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo]
+  * Fixed instanceof `Array` checks, now `Array.isArray()`
+  * Fixed express(1) expansion of public dirs. Closes #348
+  * Fixed middleware precedence. Closes #345
+  * Fixed view watcher, now async [thanks aheckmann]
+
+1.0.0beta / 2010-07-15
+==================
+
+  * Re-write
+    - much faster
+    - much lighter
+    - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs
+
+0.14.0 / 2010-06-15
+==================
+
+  * Utilize relative requires
+  * Added Static bufferSize option [aheckmann]
+  * Fixed caching of view and partial subdirectories [aheckmann]
+  * Fixed mime.type() comments now that ".ext" is not supported
+  * Updated haml submodule
+  * Updated class submodule
+  * Removed bin/express
+
+0.13.0 / 2010-06-01
+==================
+
+  * Added node v0.1.97 compatibility
+  * Added support for deleting cookies via Request#cookie('key', null)
+  * Updated haml submodule
+  * Fixed not-found page, now using using charset utf-8
+  * Fixed show-exceptions page, now using using charset utf-8
+  * Fixed view support due to fs.readFile Buffers
+  * Changed; mime.type() no longer accepts ".type" due to node extname() changes
+
+0.12.0 / 2010-05-22
+==================
+
+  * Added node v0.1.96 compatibility
+  * Added view `helpers` export which act as additional local variables
+  * Updated haml submodule
+  * Changed ETag; removed inode, modified time only
+  * Fixed LF to CRLF for setting multiple cookies
+  * Fixed cookie complation; values are now urlencoded
+  * Fixed cookies parsing; accepts quoted values and url escaped cookies
+
+0.11.0 / 2010-05-06
+==================
+
+  * Added support for layouts using different engines
+    - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
+    - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
+    - this.render('page.html.haml', { layout: false }) // no layout
+  * Updated ext submodule
+  * Updated haml submodule
+  * Fixed EJS partial support by passing along the context. Issue #307
+
+0.10.1 / 2010-05-03
+==================
+
+  * Fixed binary uploads.
+
+0.10.0 / 2010-04-30
+==================
+
+  * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
+    encoding is set to 'utf8' or 'utf-8'.
+  * Added "encoding" option to Request#render(). Closes #299
+  * Added "dump exceptions" setting, which is enabled by default.
+  * Added simple ejs template engine support
+  * Added error reponse support for text/plain, application/json. Closes #297
+  * Added callback function param to Request#error()
+  * Added Request#sendHead()
+  * Added Request#stream()
+  * Added support for Request#respond(304, null) for empty response bodies
+  * Added ETag support to Request#sendfile()
+  * Added options to Request#sendfile(), passed to fs.createReadStream()
+  * Added filename arg to Request#download()
+  * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
+  * Performance enhanced by preventing several calls to toLowerCase() in Router#match()
+  * Changed; Request#sendfile() now streams
+  * Changed; Renamed Request#halt() to Request#respond(). Closes #289
+  * Changed; Using sys.inspect() instead of JSON.encode() for error output
+  * Changed; run() returns the http.Server instance. Closes #298
+  * Changed; Defaulting Server#host to null (INADDR_ANY)
+  * Changed; Logger "common" format scale of 0.4f
+  * Removed Logger "request" format
+  * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
+  * Fixed several issues with http client
+  * Fixed Logger Content-Length output
+  * Fixed bug preventing Opera from retaining the generated session id. Closes #292
+
+0.9.0 / 2010-04-14
+==================
+
+  * Added DSL level error() route support
+  * Added DSL level notFound() route support
+  * Added Request#error()
+  * Added Request#notFound()
+  * Added Request#render() callback function. Closes #258
+  * Added "max upload size" setting
+  * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254
+  * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
+  * Added callback function support to Request#halt() as 3rd/4th arg
+  * Added preprocessing of route param wildcards using param(). Closes #251
+  * Added view partial support (with collections etc)
+  * Fixed bug preventing falsey params (such as ?page=0). Closes #286
+  * Fixed setting of multiple cookies. Closes #199
+  * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
+  * Changed; session cookie is now httpOnly
+  * Changed; Request is no longer global
+  * Changed; Event is no longer global
+  * Changed; "sys" module is no longer global
+  * Changed; moved Request#download to Static plugin where it belongs
+  * Changed; Request instance created before body parsing. Closes #262
+  * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
+  * Changed; Pre-caching view partials in memory when "cache view partials" is enabled
+  * Updated support to node --version 0.1.90
+  * Updated dependencies
+  * Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
+  * Removed utils.mixin(); use Object#mergeDeep()
+  
+0.8.0 / 2010-03-19
+==================
+
+  * Added coffeescript example app. Closes #242
+  * Changed; cache api now async friendly. Closes #240
+  * Removed deprecated 'express/static' support. Use 'express/plugins/static'
+
+0.7.6 / 2010-03-19
+==================
+
+  * Added Request#isXHR. Closes #229
+  * Added `make install` (for the executable)
+  * Added `express` executable for setting up simple app templates
+  * Added "GET /public/*" to Static plugin, defaulting to <root>/public
+  * Added Static plugin
+  * Fixed; Request#render() only calls cache.get() once
+  * Fixed; Namespacing View caches with "view:"
+  * Fixed; Namespacing Static caches with "static:"
+  * Fixed; Both example apps now use the Static plugin
+  * Fixed set("views"). Closes #239
+  * Fixed missing space for combined log format
+  * Deprecated Request#sendfile() and 'express/static'
+  * Removed Server#running
+
+0.7.5 / 2010-03-16
+==================
+
+  * Added Request#flash() support without args, now returns all flashes
+  * Updated ext submodule
+
+0.7.4 / 2010-03-16
+==================
+
+  * Fixed session reaper
+  * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)
+
+0.7.3 / 2010-03-16
+==================
+
+  * Added package.json
+  * Fixed requiring of haml / sass due to kiwi removal
+
+0.7.2 / 2010-03-16
+==================
+
+  * Fixed GIT submodules (HAH!)
+
+0.7.1 / 2010-03-16
+==================
+
+  * Changed; Express now using submodules again until a PM is adopted
+  * Changed; chat example using millisecond conversions from ext
+
+0.7.0 / 2010-03-15
+==================
+
+  * Added Request#pass() support (finds the next matching route, or the given path)
+  * Added Logger plugin (default "common" format replaces CommonLogger)
+  * Removed Profiler plugin
+  * Removed CommonLogger plugin
+
+0.6.0 / 2010-03-11
+==================
+
+  * Added seed.yml for kiwi package management support
+  * Added HTTP client query string support when method is GET. Closes #205
+  
+  * Added support for arbitrary view engines.
+    For example "foo.engine.html" will now require('engine'),
+    the exports from this module are cached after the first require().
+    
+  * Added async plugin support
+  
+  * Removed usage of RESTful route funcs as http client
+    get() etc, use http.get() and friends
+  
+  * Removed custom exceptions
+
+0.5.0 / 2010-03-10
+==================
+
+  * Added ext dependency (library of js extensions)
+  * Removed extname() / basename() utils. Use path module
+  * Removed toArray() util. Use arguments.values
+  * Removed escapeRegexp() util. Use RegExp.escape()
+  * Removed process.mixin() dependency. Use utils.mixin()
+  * Removed Collection
+  * Removed ElementCollection
+  * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com)  ;)
+
+0.4.0 / 2010-02-11
+==================
+
+  * Added flash() example to sample upload app
+  * Added high level restful http client module (express/http)
+  * Changed; RESTful route functions double as HTTP clients. Closes #69
+  * Changed; throwing error when routes are added at runtime
+  * Changed; defaulting render() context to the current Request. Closes #197
+  * Updated haml submodule
+
+0.3.0 / 2010-02-11
+==================
+
+  * Updated haml / sass submodules. Closes #200
+  * Added flash message support. Closes #64
+  * Added accepts() now allows multiple args. fixes #117
+  * Added support for plugins to halt. Closes #189
+  * Added alternate layout support. Closes #119
+  * Removed Route#run(). Closes #188
+  * Fixed broken specs due to use(Cookie) missing
+
+0.2.1 / 2010-02-05
+==================
+
+  * Added "plot" format option for Profiler (for gnuplot processing)
+  * Added request number to Profiler plugin
+  * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8
+  * Fixed issue with routes not firing when not files are present. Closes #184
+  * Fixed process.Promise -> events.Promise
+
+0.2.0 / 2010-02-03
+==================
+
+  * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180
+  * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174
+  * Added expiration support to cache api with reaper. Closes #133
+  * Added cache Store.Memory#reap()
+  * Added Cache; cache api now uses first class Cache instances
+  * Added abstract session Store. Closes #172
+  * Changed; cache Memory.Store#get() utilizing Collection
+  * Renamed MemoryStore -> Store.Memory
+  * Fixed use() of the same plugin several time will always use latest options. Closes #176
+
+0.1.0 / 2010-02-03
+==================
+
+  * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
+  * Updated node support to 0.1.27 Closes #169
+  * Updated dirname(__filename) -> __dirname
+  * Updated libxmljs support to v0.2.0
+  * Added session support with memory store / reaping
+  * Added quick uid() helper
+  * Added multi-part upload support
+  * Added Sass.js support / submodule
+  * Added production env caching view contents and static files
+  * Added static file caching. Closes #136
+  * Added cache plugin with memory stores
+  * Added support to StaticFile so that it works with non-textual files.
+  * Removed dirname() helper
+  * Removed several globals (now their modules must be required)
+
+0.0.2 / 2010-01-10
+==================
+
+  * Added view benchmarks; currently haml vs ejs
+  * Added Request#attachment() specs. Closes #116
+  * Added use of node's parseQuery() util. Closes #123
+  * Added `make init` for submodules
+  * Updated Haml
+  * Updated sample chat app to show messages on load
+  * Updated libxmljs parseString -> parseHtmlString
+  * Fixed `make init` to work with older versions of git
+  * Fixed specs can now run independant specs for those who cant build deps. Closes #127
+  * Fixed issues introduced by the node url module changes. Closes 126.
+  * Fixed two assertions failing due to Collection#keys() returning strings
+  * Fixed faulty Collection#toArray() spec due to keys() returning strings
+  * Fixed `make test` now builds libxmljs.node before testing
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/weinre.server/node_modules/express/LICENSE b/weinre.server/node_modules/express/LICENSE
new file mode 100644
index 0000000..36075a3
--- /dev/null
+++ b/weinre.server/node_modules/express/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2009-2011 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/Makefile b/weinre.server/node_modules/express/Makefile
new file mode 100644
index 0000000..dfbfd67
--- /dev/null
+++ b/weinre.server/node_modules/express/Makefile
@@ -0,0 +1,29 @@
+
+DOCS = $(shell find docs/*.md)
+HTMLDOCS = $(DOCS:.md=.html)
+TESTS = $(shell find test/*.test.js)
+
+test:
+	@NODE_ENV=test ./node_modules/.bin/expresso $(TESTS)
+
+docs: $(HTMLDOCS)
+	@ echo "... generating TOC"
+	@./support/toc.js docs/guide.html
+
+%.html: %.md
+	@echo "... $< -> $@"
+	@markdown $< \
+	  | cat docs/layout/head.html - docs/layout/foot.html \
+	  > $@
+
+site:
+	rm -fr /tmp/docs \
+	  && cp -fr docs /tmp/docs \
+	  && git checkout gh-pages \
+  	&& cp -fr /tmp/docs/* . \
+		&& echo "done"
+
+docclean:
+	rm -f docs/*.{1,html}
+
+.PHONY: site test docs docclean
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/Readme.md b/weinre.server/node_modules/express/Readme.md
new file mode 100644
index 0000000..d2c64c7
--- /dev/null
+++ b/weinre.server/node_modules/express/Readme.md
@@ -0,0 +1,145 @@
+
+# Express
+      
+  Insanely fast (and small) server-side JavaScript web development framework
+  built on [node](http://nodejs.org) and [Connect](http://github.com/senchalabs/connect).
+  
+     var app = express.createServer();
+     
+     app.get('/', function(req, res){
+       res.send('Hello World');
+     });
+     
+     app.listen(3000);
+
+## Installation
+
+    $ npm install express
+
+or to access the `express(1)` executable install globally:
+
+    $ npm install -g express
+
+## Quick Start
+
+ The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
+
+ Create the app:
+
+    $ npm install -g express
+    $ express /tmp/foo && cd /tmp/foo
+
+ Install dependencies:
+
+    $ npm install -d
+
+ Start the server:
+
+    $ node app.js
+
+## Features
+
+  * Robust routing
+  * Redirection helpers
+  * Dynamic view helpers
+  * Content negotiation
+  * Focus on high performance
+  * View rendering and partials support
+  * Environment based configuration
+  * Session based flash notifications
+  * Built on [Connect](http://github.com/senchalabs/connect)
+  * High test coverage
+  * Executable for generating applications quickly
+  * Application level view options
+
+Via Connect:
+
+  * Session support
+  * Cache API
+  * Mime helpers
+  * ETag support
+  * Persistent flash notifications
+  * Cookie support
+  * JSON-RPC
+  * Logging
+  * and _much_ more!
+
+## Contributors
+
+The following are the major contributors of Express (in no specific order).
+
+  * TJ Holowaychuk ([visionmedia](http://github.com/visionmedia))
+  * Ciaran Jessup ([ciaranj](http://github.com/ciaranj))
+  * Aaron Heckmann ([aheckmann](http://github.com/aheckmann))
+  * Guillermo Rauch ([guille](http://github.com/guille))
+
+## More Information
+
+  * #express on freenode
+  * [express-expose](http://github.com/visionmedia/express-expose) expose objects, functions, modules and more to client-side js with ease
+  * [express-configure](http://github.com/visionmedia/express-configuration) async configuration support
+  * [express-messages](http://github.com/visionmedia/express-messages) flash notification rendering helper
+  * [express-namespace](http://github.com/visionmedia/express-namespace) namespaced route support
+  * [express-params](https://github.com/visionmedia/express-params) param pre-condition functions
+  * [express-mongoose](https://github.com/LearnBoost/express-mongoose) plugin for easy rendering of Mongoose async Query results
+  * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
+  * [Google Group](http://groups.google.com/group/express-js) for discussion
+  * Visit the [Wiki](http://github.com/visionmedia/express/wiki)
+  * [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
+  * Screencast - [Introduction](http://bit.ly/eRYu0O)
+  * Screencast - [View Partials](http://bit.ly/dU13Fx)
+  * Screencast - [Route Specific Middleware](http://bit.ly/hX4IaH)
+  * Screencast - [Route Path Placeholder Preconditions](http://bit.ly/eNqmVs)
+
+## Node Compatibility
+
+Express 1.x is compatible with node 0.2.x and connect < 1.0.
+
+Express 2.x is compatible with node 0.4.x or 0.6.x, and connect 1.x
+
+Express 3.x (master) will be compatible with node 0.6.x and connect 2.x
+
+## Viewing Examples
+
+First install the dev dependencies to install all the example / test suite deps:
+
+    $ npm install
+
+then run whichever tests you want:
+
+    $ node examples/jade/app.js
+
+## Running Tests
+
+To run the test suite first invoke the following command within the repo, installing the development dependencies:
+
+    $ npm install
+
+then run the tests:
+
+    $ make test
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2009-2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/weinre.server/node_modules/express/bin/express b/weinre.server/node_modules/express/bin/express
new file mode 100755
index 0000000..f28a0fd
--- /dev/null
+++ b/weinre.server/node_modules/express/bin/express
@@ -0,0 +1,416 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , os = require('os')
+  , exec = require('child_process').exec
+  , mkdirp = require('mkdirp');
+
+/**
+ * Framework version.
+ */
+
+var version = '2.5.7';
+
+/**
+ * Add session support.
+ */
+
+var sessions = false;
+
+/**
+ * CSS engine to utilize.
+ */
+
+var cssEngine;
+
+/**
+ * End-of-line code.
+ */
+
+var eol = os.platform
+  ? ('win32' == os.platform() ? '\r\n' : '\n')
+  : '\n';
+
+/**
+ * Template engine to utilize.
+ */
+
+var templateEngine = 'jade';
+
+/**
+ * Usage documentation.
+ */
+
+var usage = ''
+  + '\n'
+  + '  Usage: express [options] [path]\n'
+  + '\n'
+  + '  Options:\n'
+  + '    -s, --sessions           add session support\n'
+  + '    -t, --template <engine>  add template <engine> support (jade|ejs). default=jade\n'
+  + '    -c, --css <engine>       add stylesheet <engine> support (stylus). default=plain css\n'
+  + '    -v, --version            output framework version\n'
+  + '    -h, --help               output help information\n'
+  ;
+
+/**
+ * Routes index template.
+ */
+
+var index = [
+    ''
+  , '/*'
+  , ' * GET home page.'
+  , ' */'
+  , ''
+  , 'exports.index = function(req, res){'
+  , '  res.render(\'index\', { title: \'Express\' })'
+  , '};'
+].join(eol);
+
+/**
+ * Jade layout template.
+ */
+
+var jadeLayout = [
+    '!!!'
+  , 'html'
+  , '  head'
+  , '    title= title'
+  , '    link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
+  , '  body!= body'
+].join(eol);
+
+/**
+ * Jade index template.
+ */
+
+var jadeIndex = [
+    'h1= title'
+  , 'p Welcome to #{title}'
+].join(eol);
+
+/**
+ * EJS layout template.
+ */
+
+var ejsLayout = [
+    '<!DOCTYPE html>'
+  , '<html>'
+  , '  <head>'
+  , '    <title><%= title %></title>'
+  , '    <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
+  , '  </head>'
+  , '  <body>'
+  , '    <%- body %>'
+  , '  </body>'
+  , '</html>'
+].join(eol);
+
+/**
+ * EJS index template.
+ */
+
+var ejsIndex = [
+    '<h1><%= title %></h1>'
+  , '<p>Welcome to <%= title %></p>'
+  ].join(eol);
+
+/**
+ * Default css template.
+ */
+
+var css = [
+    'body {'
+  , '  padding: 50px;'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+  , '}'
+  , ''
+  , 'a {'
+  , '  color: #00B7FF;'
+  , '}'
+].join(eol);
+
+/**
+ * Default stylus template.
+ */
+
+var stylus = [
+    'body'
+  , '  padding: 50px'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
+  , 'a'
+  , '  color: #00B7FF'
+].join(eol);
+
+/**
+ * App template.
+ */
+
+var app = [
+    ''
+  , '/**'
+  , ' * Module dependencies.'
+  , ' */'
+  , ''
+  , 'var express = require(\'express\')'
+  , '  , routes = require(\'./routes\');'
+  , ''
+  , 'var app = module.exports = express.createServer();'
+  , ''
+  , '// Configuration'
+  , ''
+  , 'app.configure(function(){'
+  , '  app.set(\'views\', __dirname + \'/views\');'
+  , '  app.set(\'view engine\', \':TEMPLATE\');'
+  , '  app.use(express.bodyParser());'
+  , '  app.use(express.methodOverride());{sess}{css}'
+  , '  app.use(app.router);'
+  , '  app.use(express.static(__dirname + \'/public\'));'
+  , '});'
+  , ''
+  , 'app.configure(\'development\', function(){'
+  , '  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));'
+  , '});'
+  , ''
+  , 'app.configure(\'production\', function(){'
+  , '  app.use(express.errorHandler());'
+  , '});'
+  , ''
+  , '// Routes'
+  , ''
+  , 'app.get(\'/\', routes.index);'
+  , ''
+  , 'app.listen(3000);'
+  , 'console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);'
+  , ''
+].join(eol);
+
+// Parse arguments
+
+var args = process.argv.slice(2)
+  , path = '.';
+
+while (args.length) {
+  var arg = args.shift();
+  switch (arg) {
+    case '-h':
+    case '--help':
+      abort(usage);
+      break;
+    case '-v':
+    case '--version':
+      abort(version);
+      break;
+    case '-s':
+    case '--session':
+    case '--sessions':
+      sessions = true;
+      break;
+    case '-c':
+    case '--css':
+      args.length
+        ? (cssEngine = args.shift())
+        : abort('--css requires an argument');
+      break;
+    case '-t':
+    case '--template':
+      args.length
+        ? (templateEngine = args.shift())
+        : abort('--template requires an argument');
+      break;
+    default:
+        path = arg;
+  }
+}
+
+// Generate application
+
+(function createApplication(path) {
+  emptyDirectory(path, function(empty){
+    if (empty) {
+      createApplicationAt(path);
+    } else {
+      confirm('destination is not empty, continue? ', function(ok){
+        if (ok) {
+          process.stdin.destroy();
+          createApplicationAt(path);
+        } else {
+          abort('aborting');
+        }
+      });
+    }
+  });
+})(path);
+
+/**
+ * Create application at the given directory `path`.
+ *
+ * @param {String} path
+ */
+
+function createApplicationAt(path) {
+  console.log();
+  process.on('exit', function(){
+    console.log();
+    console.log('   dont forget to install dependencies:');
+    console.log('   $ cd %s && npm install', path);
+    console.log();
+  });
+
+  mkdir(path, function(){
+    mkdir(path + '/public');
+    mkdir(path + '/public/javascripts');
+    mkdir(path + '/public/images');
+    mkdir(path + '/public/stylesheets', function(){
+      switch (cssEngine) {
+        case 'stylus':
+          write(path + '/public/stylesheets/style.styl', stylus);
+          break;
+        default:
+          write(path + '/public/stylesheets/style.css', css);
+      }
+    });
+
+    mkdir(path + '/routes', function(){
+      write(path + '/routes/index.js', index);
+    });
+
+    mkdir(path + '/views', function(){
+      switch (templateEngine) {
+        case 'ejs':
+          write(path + '/views/layout.ejs', ejsLayout);
+          write(path + '/views/index.ejs', ejsIndex);
+          break;
+        case 'jade':
+          write(path + '/views/layout.jade', jadeLayout);
+          write(path + '/views/index.jade', jadeIndex);
+          break;
+      }
+    });
+
+    // CSS Engine support
+    switch (cssEngine) {
+      case 'stylus':
+        app = app.replace('{css}', eol + '  app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
+        break;
+      default:
+        app = app.replace('{css}', '');
+    }
+
+    // Session support
+    app = app.replace('{sess}', sessions
+      ? eol + '  app.use(express.cookieParser());' + eol + '  app.use(express.session({ secret: \'your secret here\' }));'
+      : '');
+
+    // Template support
+    app = app.replace(':TEMPLATE', templateEngine);
+
+    // package.json
+    var json = '{' + eol;
+    json += '    "name": "application-name"' + eol;
+    json += '  , "version": "0.0.1"' + eol;
+    json += '  , "private": true' + eol;
+    json += '  , "dependencies": {' + eol;
+    json += '      "express": "' + version + '"' + eol;
+    if (cssEngine) json += '    , "' + cssEngine + '": ">= 0.0.1"' + eol;
+    if (templateEngine) json += '    , "' + templateEngine + '": ">= 0.0.1"' + eol;
+    json += '  }' + eol;
+    json += '}';
+
+
+    write(path + '/package.json', json);
+    write(path + '/app.js', app);
+  });
+}
+
+/**
+ * Check if the given directory `path` is empty.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function emptyDirectory(path, fn) {
+  fs.readdir(path, function(err, files){
+    if (err && 'ENOENT' != err.code) throw err;
+    fn(!files || !files.length);
+  });
+}
+
+/**
+ * echo str > path.
+ *
+ * @param {String} path
+ * @param {String} str
+ */
+
+function write(path, str) {
+  fs.writeFile(path, str);
+  console.log('   \x1b[36mcreate\x1b[0m : ' + path);
+}
+
+/**
+ * Prompt confirmation with the given `msg`.
+ *
+ * @param {String} msg
+ * @param {Function} fn
+ */
+
+function confirm(msg, fn) {
+  prompt(msg, function(val){
+    fn(/^ *y(es)?/i.test(val));
+  });
+}
+
+/**
+ * Prompt input with the given `msg` and callback `fn`.
+ *
+ * @param {String} msg
+ * @param {Function} fn
+ */
+
+function prompt(msg, fn) {
+  // prompt
+  if (' ' == msg[msg.length - 1]) {
+    process.stdout.write(msg);
+  } else {
+    console.log(msg);
+  }
+
+  // stdin
+  process.stdin.setEncoding('ascii');
+  process.stdin.once('data', function(data){
+    fn(data);
+  }).resume();
+}
+
+/**
+ * Mkdir -p.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function mkdir(path, fn) {
+  mkdirp(path, 0755, function(err){
+    if (err) throw err;
+    console.log('   \033[36mcreate\033[0m : ' + path);
+    fn && fn();
+  });
+}
+
+/**
+ * Exit with the given `str`.
+ *
+ * @param {String} str
+ */
+
+function abort(str) {
+  console.error(str);
+  process.exit(1);
+}
diff --git a/weinre.server/node_modules/express/index.js b/weinre.server/node_modules/express/index.js
new file mode 100644
index 0000000..8d81ea7
--- /dev/null
+++ b/weinre.server/node_modules/express/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/express');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/lib/express.js b/weinre.server/node_modules/express/lib/express.js
new file mode 100644
index 0000000..029dcc9
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/express.js
@@ -0,0 +1,79 @@
+
+/*!
+ * Express
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+  , HTTPSServer = require('./https')
+  , HTTPServer = require('./http')
+  , Route = require('./router/route')
+
+/**
+ * Re-export connect auto-loaders.
+ * 
+ * This prevents the need to `require('connect')` in order
+ * to access core middleware, so for example `express.logger()` instead
+ * of `require('connect').logger()`.
+ */
+
+var exports = module.exports = connect.middleware;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '2.5.7';
+
+/**
+ * Shortcut for `new Server(...)`.
+ *
+ * @param {Function} ...
+ * @return {Server}
+ * @api public
+ */
+
+exports.createServer = function(options){
+  if ('object' == typeof options) {
+    return new HTTPSServer(options, Array.prototype.slice.call(arguments, 1));
+  } else {
+    return new HTTPServer(Array.prototype.slice.call(arguments));
+  }
+};
+
+/**
+ * Expose constructors.
+ */
+
+exports.HTTPServer = HTTPServer;
+exports.HTTPSServer = HTTPSServer;
+exports.Route = Route;
+
+/**
+ * View extensions.
+ */
+
+exports.View =
+exports.view = require('./view');
+
+/**
+ * Response extensions.
+ */
+
+require('./response');
+
+/**
+ * Request extensions.
+ */
+
+require('./request');
+
+// Error handler title
+
+exports.errorHandler.title = 'Express';
+
diff --git a/weinre.server/node_modules/express/lib/http.js b/weinre.server/node_modules/express/lib/http.js
new file mode 100644
index 0000000..da2158f
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/http.js
@@ -0,0 +1,582 @@
+/*!
+ * Express - HTTPServer
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+  , connect = require('connect')
+  , router = require('./router')
+  , Router = require('./router')
+  , view = require('./view')
+  , toArray = require('./utils').toArray
+  , methods = router.methods.concat('del', 'all')
+  , url = require('url')
+  , utils = connect.utils;
+
+/**
+ * Expose `HTTPServer`.
+ */
+
+exports = module.exports = HTTPServer;
+
+/**
+ * Server proto.
+ */
+
+var app = HTTPServer.prototype;
+
+/**
+ * Initialize a new `HTTPServer` with optional `middleware`.
+ *
+ * @param {Array} middleware
+ * @api public
+ */
+
+function HTTPServer(middleware){
+  connect.HTTPServer.call(this, []);
+  this.init(middleware);
+};
+
+/**
+ * Inherit from `connect.HTTPServer`.
+ */
+
+app.__proto__ = connect.HTTPServer.prototype;
+
+/**
+ * Initialize the server.
+ *
+ * @param {Array} middleware
+ * @api private
+ */
+
+app.init = function(middleware){
+  var self = this;
+  this.cache = {};
+  this.settings = {};
+  this.redirects = {};
+  this.isCallbacks = {};
+  this._locals = {};
+  this.dynamicViewHelpers = {};
+  this.errorHandlers = [];
+
+  this.set('env', process.env.NODE_ENV || 'development');
+
+  // expose objects to each other
+  this.use(function(req, res, next){
+    req.query = req.query || {};
+    res.setHeader('X-Powered-By', 'Express');
+    req.app = res.app = self;
+    req.res = res;
+    res.req = req;
+    req.next = next;
+    // assign req.query
+    if (req.url.indexOf('?') > 0) {
+      var query = url.parse(req.url).query;
+      req.query = qs.parse(query);
+    }
+    next();
+  });
+
+  // apply middleware
+  if (middleware) middleware.forEach(self.use.bind(self));
+
+  // router
+  this.routes = new Router(this);
+  this.__defineGetter__('router', function(){
+    this.__usedRouter = true;
+    return self.routes.middleware;
+  });
+
+  // default locals
+  this.locals({
+      settings: this.settings
+    , app: this
+  });
+
+  // default development configuration
+  this.configure('development', function(){
+    this.enable('hints');
+  });
+
+  // default production configuration
+  this.configure('production', function(){
+    this.enable('view cache');
+  });
+
+  // register error handlers on "listening"
+  // so that they disregard definition position.
+  this.on('listening', this.registerErrorHandlers.bind(this));
+
+  // route manipulation methods
+  methods.forEach(function(method){
+    self.lookup[method] = function(path){
+      return self.routes.lookup(method, path);
+    };
+
+    self.match[method] = function(path){
+      return self.routes.match(method, path);
+    };
+
+    self.remove[method] = function(path){
+      return self.routes.lookup(method, path).remove();
+    };
+  });
+
+  // del -> delete
+  self.lookup.del = self.lookup.delete;
+  self.match.del = self.match.delete;
+  self.remove.del = self.remove.delete;
+};
+
+/**
+ * Remove routes matching the given `path`.
+ *
+ * @param {Route} path
+ * @return {Boolean}
+ * @api public
+ */
+
+app.remove = function(path){
+  return this.routes.lookup('all', path).remove();
+};
+
+/**
+ * Lookup routes defined with a path
+ * equivalent to `path`.
+ *
+ * @param {Stirng} path
+ * @return {Array}
+ * @api public
+ */
+
+app.lookup = function(path){
+  return this.routes.lookup('all', path);
+};
+
+/**
+ * Lookup routes matching the given `url`.
+ *
+ * @param {Stirng} url
+ * @return {Array}
+ * @api public
+ */
+
+app.match = function(url){
+  return this.routes.match('all', url);
+};
+
+/**
+ * When using the vhost() middleware register error handlers.
+ */
+
+app.onvhost = function(){
+  this.registerErrorHandlers();
+};
+
+/**
+ * Register error handlers.
+ *
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.registerErrorHandlers = function(){
+  this.errorHandlers.forEach(function(fn){
+    this.use(function(err, req, res, next){
+      fn.apply(this, arguments);
+    });
+  }, this);
+  return this;
+};
+
+/**
+ * Proxy `connect.HTTPServer#use()` to apply settings to
+ * mounted applications.
+ *
+ * @param {String|Function|Server} route
+ * @param {Function|Server} middleware
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.use = function(route, middleware){
+  var app, base, handle;
+
+  if ('string' != typeof route) {
+    middleware = route, route = '/';
+  }
+
+  // express app
+  if (middleware.handle && middleware.set) app = middleware;
+
+  // restore .app property on req and res
+  if (app) {
+    app.route = route;
+    middleware = function(req, res, next) {
+      var orig = req.app;
+      app.handle(req, res, function(err){
+        req.app = res.app = orig;
+        next(err);
+      });
+    };
+  }
+
+  connect.HTTPServer.prototype.use.call(this, route, middleware);
+
+  // mounted an app, invoke the hook
+  // and adjust some settings
+  if (app) {
+    base = this.set('basepath') || this.route;
+    if ('/' == base) base = '';
+    base = base + (app.set('basepath') || app.route);
+    app.set('basepath', base);
+    app.parent = this;
+    if (app.__mounted) app.__mounted.call(app, this);
+  }
+
+  return this;
+};
+
+/**
+ * Assign a callback `fn` which is called
+ * when this `Server` is passed to `Server#use()`.
+ *
+ * Examples:
+ *
+ *    var app = express.createServer()
+ *      , blog = express.createServer();
+ *
+ *    blog.mounted(function(parent){
+ *      // parent is app
+ *      // "this" is blog
+ *    });
+ *
+ *    app.use(blog);
+ *
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.mounted = function(fn){
+  this.__mounted = fn;
+  return this;
+};
+
+/**
+ * See: view.register.
+ *
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.register = function(){
+  view.register.apply(this, arguments);
+  return this;
+};
+
+/**
+ * Register the given view helpers `obj`. This method
+ * can be called several times to apply additional helpers.
+ *
+ * @param {Object} obj
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.helpers =
+app.locals = function(obj){
+  utils.merge(this._locals, obj);
+  return this;
+};
+
+/**
+ * Register the given dynamic view helpers `obj`. This method
+ * can be called several times to apply additional helpers.
+ *
+ * @param {Object} obj
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.dynamicHelpers = function(obj){
+  utils.merge(this.dynamicViewHelpers, obj);
+  return this;
+};
+
+/**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Param mapping is used to provide pre-conditions to routes
+ * which us normalized placeholders. This callback has the same
+ * signature as regular middleware, for example below when ":userId"
+ * is used this function will be invoked in an attempt to load the user.
+ *
+ *      app.param('userId', function(req, res, next, id){
+ *        User.find(id, function(err, user){
+ *          if (err) {
+ *            next(err);
+ *          } else if (user) {
+ *            req.user = user;
+ *            next();
+ *          } else {
+ *            next(new Error('failed to load user'));
+ *          }
+ *        });
+ *      });
+ *
+ * Passing a single function allows you to map logic
+ * to the values passed to `app.param()`, for example
+ * this is useful to provide coercion support in a concise manner.
+ *
+ * The following example maps regular expressions to param values
+ * ensuring that they match, otherwise passing control to the next
+ * route:
+ *
+ *      app.param(function(name, regexp){
+ *        if (regexp instanceof RegExp) {
+ *          return function(req, res, next, val){
+ *            var captures;
+ *            if (captures = regexp.exec(String(val))) {
+ *              req.params[name] = captures;
+ *              next();
+ *            } else {
+ *              next('route');
+ *            }
+ *          }
+ *        }
+ *      });
+ *
+ * We can now use it as shown below, where "/commit/:commit" expects
+ * that the value for ":commit" is at 5 or more digits. The capture
+ * groups are then available as `req.params.commit` as we defined
+ * in the function above.
+ *
+ *    app.param('commit', /^\d{5,}$/);
+ *
+ * For more of this useful functionality take a look
+ * at [express-params](http://github.com/visionmedia/express-params).
+ *
+ * @param {String|Array|Function} name
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.param = function(name, fn){
+  var self = this
+    , fns = [].slice.call(arguments, 1);
+
+  // array
+  if (Array.isArray(name)) {
+    name.forEach(function(name){
+      fns.forEach(function(fn){
+        self.param(name, fn);
+      });
+    });
+  // param logic
+  } else if ('function' == typeof name) {
+    this.routes.param(name);
+  // single
+  } else {
+    if (':' == name[0]) name = name.substr(1);
+    fns.forEach(function(fn){
+      self.routes.param(name, fn);
+    });
+  }
+
+  return this;
+};
+
+/**
+ * Assign a custom exception handler callback `fn`.
+ * These handlers are always _last_ in the middleware stack.
+ *
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.error = function(fn){
+  this.errorHandlers.push(fn);
+  return this;
+};
+
+/**
+ * Register the given callback `fn` for the given `type`.
+ *
+ * @param {String} type
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.is = function(type, fn){
+  if (!fn) return this.isCallbacks[type];
+  this.isCallbacks[type] = fn;
+  return this;
+};
+
+/**
+ * Assign `setting` to `val`, or return `setting`'s value.
+ * Mounted servers inherit their parent server's settings.
+ *
+ * @param {String} setting
+ * @param {String} val
+ * @return {Server|Mixed} for chaining, or the setting value
+ * @api public
+ */
+
+app.set = function(setting, val){
+  if (val === undefined) {
+    if (this.settings.hasOwnProperty(setting)) {
+      return this.settings[setting];
+    } else if (this.parent) {
+      return this.parent.set(setting);
+    }
+  } else {
+    this.settings[setting] = val;
+    return this;
+  }
+};
+
+/**
+ * Check if `setting` is enabled.
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.enabled = function(setting){
+  return !!this.set(setting);
+};
+
+/**
+ * Check if `setting` is disabled.
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.disabled = function(setting){
+  return !this.set(setting);
+};
+
+/**
+ * Enable `setting`.
+ *
+ * @param {String} setting
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.enable = function(setting){
+  return this.set(setting, true);
+};
+
+/**
+ * Disable `setting`.
+ *
+ * @param {String} setting
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.disable = function(setting){
+  return this.set(setting, false);
+};
+
+/**
+ * Redirect `key` to `url`.
+ *
+ * @param {String} key
+ * @param {String} url
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.redirect = function(key, url){
+  this.redirects[key] = url;
+  return this;
+};
+
+/**
+ * Configure callback for zero or more envs,
+ * when no env is specified that callback will
+ * be invoked for all environments. Any combination
+ * can be used multiple times, in any order desired.
+ *
+ * Examples:
+ *
+ *    app.configure(function(){
+ *      // executed for all envs
+ *    });
+ *
+ *    app.configure('stage', function(){
+ *      // executed staging env
+ *    });
+ *
+ *    app.configure('stage', 'production', function(){
+ *      // executed for stage and production
+ *    });
+ *
+ * @param {String} env...
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.configure = function(env, fn){
+  var envs = 'all'
+    , args = toArray(arguments);
+  fn = args.pop();
+  if (args.length) envs = args;
+  if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
+  return this;
+};
+
+/**
+ * Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
+ */
+
+methods.forEach(function(method){
+  app[method] = function(path){
+    if (1 == arguments.length) return this.routes.lookup(method, path);
+    var args = [method].concat(toArray(arguments));
+    if (!this.__usedRouter) this.use(this.router);
+    return this.routes._route.apply(this.routes, args);
+  }
+});
+
+/**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ *
+ * @param {String} path
+ * @param {Function} ...
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.all = function(path){
+  var args = arguments;
+  if (1 == args.length) return this.routes.lookup('all', path);
+  methods.forEach(function(method){
+    if ('all' == method || 'del' == method) return;
+    app[method].apply(this, args);
+  }, this);
+  return this;
+};
+
+// del -> delete alias
+
+app.del = app.delete;
+
diff --git a/weinre.server/node_modules/express/lib/https.js b/weinre.server/node_modules/express/lib/https.js
new file mode 100644
index 0000000..8a8c008
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/https.js
@@ -0,0 +1,52 @@
+
+/*!
+ * Express - HTTPSServer
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+  , HTTPServer = require('./http')
+  , https = require('https');
+
+/**
+ * Expose `HTTPSServer`.
+ */
+
+exports = module.exports = HTTPSServer;
+
+/**
+ * Server proto.
+ */
+
+var app = HTTPSServer.prototype;
+
+/**
+ * Initialize a new `HTTPSServer` with the 
+ * given `options`, and optional `middleware`.
+ *
+ * @param {Object} options
+ * @param {Array} middleware
+ * @api public
+ */
+
+function HTTPSServer(options, middleware){
+  connect.HTTPSServer.call(this, options, []);
+  this.init(middleware);
+};
+
+/**
+ * Inherit from `connect.HTTPSServer`.
+ */
+
+app.__proto__ = connect.HTTPSServer.prototype;
+
+// mixin HTTPServer methods
+
+Object.keys(HTTPServer.prototype).forEach(function(method){
+  app[method] = HTTPServer.prototype[method];
+});
diff --git a/weinre.server/node_modules/express/lib/request.js b/weinre.server/node_modules/express/lib/request.js
new file mode 100644
index 0000000..1d5ab40
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/request.js
@@ -0,0 +1,323 @@
+
+/*!
+ * Express - request
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , req = http.IncomingMessage.prototype
+  , utils = require('./utils')
+  , parse = require('url').parse
+  , mime = require('mime');
+
+/**
+ * Default flash formatters.
+ *
+ * @type Object
+ */
+
+var flashFormatters = exports.flashFormatters = {
+  s: function(val){
+    return String(val);
+  }
+};
+
+/**
+ * Return request header or optional default.
+ *
+ * The `Referrer` header field is special-cased,
+ * both `Referrer` and `Referer` will yield are
+ * interchangeable.
+ *
+ * Examples:
+ *
+ *     req.header('Content-Type');
+ *     // => "text/plain"
+ *     
+ *     req.header('content-type');
+ *     // => "text/plain"
+ *     
+ *     req.header('Accept');
+ *     // => undefined
+ *     
+ *     req.header('Accept', 'text/html');
+ *     // => "text/html"
+ *
+ * @param {String} name
+ * @param {String} defaultValue
+ * @return {String} 
+ * @api public
+ */
+
+req.header = function(name, defaultValue){
+  switch (name = name.toLowerCase()) {
+    case 'referer':
+    case 'referrer':
+      return this.headers.referrer
+        || this.headers.referer
+        || defaultValue;
+    default:
+      return this.headers[name] || defaultValue;
+  }
+};
+
+/**
+ * Get `field`'s `param` value, defaulting to ''.
+ *
+ * Examples:
+ *
+ *     req.get('content-disposition', 'filename');
+ *     // => "something.png"
+ *
+ * @param {String} field
+ * @param {String} param
+ * @return {String}
+ * @api public
+ */
+
+req.get = function(field, param){
+  var val = this.header(field);
+  if (!val) return '';
+  var regexp = new RegExp(param + ' *= *(?:"([^"]+)"|([^;]+))', 'i');
+  if (!regexp.exec(val)) return '';
+  return RegExp.$1 || RegExp.$2;
+};
+
+/**
+ * Short-hand for `require('url').parse(req.url).pathname`.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('path', function(){
+  return parse(this.url).pathname;
+});
+
+/**
+ * Check if the _Accept_ header is present, and includes the given `type`.
+ *
+ * When the _Accept_ header is not present `true` is returned. Otherwise
+ * the given `type` is matched by an exact match, and then subtypes. You
+ * may pass the subtype such as "html" which is then converted internally
+ * to "text/html" using the mime lookup table.
+ *
+ * Examples:
+ * 
+ *     // Accept: text/html
+ *     req.accepts('html');
+ *     // => true
+ *
+ *     // Accept: text/*; application/json
+ *     req.accepts('html');
+ *     req.accepts('text/html');
+ *     req.accepts('text/plain');
+ *     req.accepts('application/json');
+ *     // => true
+ *
+ *     req.accepts('image/png');
+ *     req.accepts('png');
+ *     // => false
+ *
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.accepts = function(type){
+  var accept = this.header('Accept');
+
+  // normalize extensions ".json" -> "json"
+  if (type && '.' == type[0]) type = type.substr(1);
+
+  // when Accept does not exist, or is '*/*' return true 
+  if (!accept || '*/*' == accept) {
+    return true;
+  } else if (type) {
+    // allow "html" vs "text/html" etc
+    if (!~type.indexOf('/')) type = mime.lookup(type);
+
+    // check if we have a direct match
+    if (~accept.indexOf(type)) return true;
+
+    // check if we have type/*
+    type = type.split('/')[0] + '/*';
+    return !!~accept.indexOf(type);
+  } else {
+    return false;
+  }
+};
+
+/**
+ * Return the value of param `name` when present or `defaultValue`.
+ *
+ *  - Checks route placeholders, ex: _/user/:id_
+ *  - Checks query string params, ex: ?id=12
+ *  - Checks urlencoded body params, ex: id=12
+ *
+ * To utilize urlencoded request bodies, `req.body`
+ * should be an object. This can be done by using
+ * the `connect.bodyParser` middleware.
+ *
+ * @param {String} name
+ * @param {Mixed} defaultValue
+ * @return {String}
+ * @api public
+ */
+
+req.param = function(name, defaultValue){
+  // route params like /user/:id
+  if (this.params && this.params.hasOwnProperty(name) && undefined !== this.params[name]) {
+    return this.params[name]; 
+  }
+  // query string params
+  if (undefined !== this.query[name]) {
+    return this.query[name]; 
+  }
+  // request body params via connect.bodyParser
+  if (this.body && undefined !== this.body[name]) {
+    return this.body[name];
+  }
+  return defaultValue;
+};
+
+/**
+ * Queue flash `msg` of the given `type`.
+ *
+ * Examples:
+ *
+ *      req.flash('info', 'email sent');
+ *      req.flash('error', 'email delivery failed');
+ *      req.flash('info', 'email re-sent');
+ *      // => 2
+ *
+ *      req.flash('info');
+ *      // => ['email sent', 'email re-sent']
+ *
+ *      req.flash('info');
+ *      // => []
+ *
+ *      req.flash();
+ *      // => { error: ['email delivery failed'], info: [] }
+ *
+ * Formatting:
+ *
+ * Flash notifications also support arbitrary formatting support.
+ * For example you may pass variable arguments to `req.flash()`
+ * and use the %s specifier to be replaced by the associated argument:
+ *
+ *     req.flash('info', 'email has been sent to %s.', userName);
+ *
+ * To add custom formatters use the `exports.flashFormatters` object.
+ *
+ * @param {String} type
+ * @param {String} msg
+ * @return {Array|Object|Number}
+ * @api public
+ */
+
+req.flash = function(type, msg){
+  if (this.session === undefined) throw Error('req.flash() requires sessions');
+  var msgs = this.session.flash = this.session.flash || {};
+  if (type && msg) {
+    var i = 2
+      , args = arguments
+      , formatters = this.app.flashFormatters || {};
+    formatters.__proto__ = flashFormatters;
+    msg = utils.miniMarkdown(msg);
+    msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
+      var formatter = formatters[format];
+      if (formatter) return formatter(utils.escape(args[i++]));
+    });
+    return (msgs[type] = msgs[type] || []).push(msg);
+  } else if (type) {
+    var arr = msgs[type];
+    delete msgs[type];
+    return arr || [];
+  } else {
+    this.session.flash = {};
+    return msgs;
+  }
+};
+
+/**
+ * Check if the incoming request contains the "Content-Type" 
+ * header field, and it contains the give mime `type`.
+ *
+ * Examples:
+ *
+ *      // With Content-Type: text/html; charset=utf-8
+ *      req.is('html');
+ *      req.is('text/html');
+ *      // => true
+ *     
+ *      // When Content-Type is application/json
+ *      req.is('json');
+ *      req.is('application/json');
+ *      // => true
+ *     
+ *      req.is('html');
+ *      // => false
+ * 
+ * Ad-hoc callbacks can also be registered with Express, to perform
+ * assertions again the request, for example if we need an expressive
+ * way to check if our incoming request is an image, we can register "an image"
+ * callback:
+ * 
+ *       app.is('an image', function(req){
+ *         return 0 == req.headers['content-type'].indexOf('image');
+ *       });
+ *       
+ *  Now within our route callbacks, we can use to to assert content types
+ *  such as "image/jpeg", "image/png", etc.
+ * 
+ *      app.post('/image/upload', function(req, res, next){
+ *        if (req.is('an image')) {
+ *          // do something
+ *        } else {
+ *          next();
+ *        }
+ *      });
+ * 
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.is = function(type){
+  var fn = this.app.is(type);
+  if (fn) return fn(this);
+  var ct = this.headers['content-type'];
+  if (!ct) return false;
+  ct = ct.split(';')[0];
+  if (!~type.indexOf('/')) type = mime.lookup(type);
+  if (~type.indexOf('*')) {
+    type = type.split('/');
+    ct = ct.split('/');
+    if ('*' == type[0] && type[1] == ct[1]) return true;
+    if ('*' == type[1] && type[0] == ct[0]) return true;
+    return false;
+  }
+  return !! ~ct.indexOf(type);
+};
+
+// Callback for isXMLHttpRequest / xhr
+
+function isxhr() {
+  return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
+}
+
+/**
+ * Check if the request was an _XMLHttpRequest_.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('isXMLHttpRequest', isxhr);
+req.__defineGetter__('xhr', isxhr);
diff --git a/weinre.server/node_modules/express/lib/response.js b/weinre.server/node_modules/express/lib/response.js
new file mode 100644
index 0000000..a671771
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/response.js
@@ -0,0 +1,460 @@
+
+/*!
+ * Express - response
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , http = require('http')
+  , path = require('path')
+  , connect = require('connect')
+  , utils = connect.utils
+  , parseRange = require('./utils').parseRange
+  , res = http.ServerResponse.prototype
+  , send = connect.static.send
+  , mime = require('mime')
+  , basename = path.basename
+  , join = path.join;
+
+/**
+ * Send a response with the given `body` and optional `headers` and `status` code.
+ *
+ * Examples:
+ *
+ *     res.send();
+ *     res.send(new Buffer('wahoo'));
+ *     res.send({ some: 'json' });
+ *     res.send('<p>some html</p>');
+ *     res.send('Sorry, cant find that', 404);
+ *     res.send('text', { 'Content-Type': 'text/plain' }, 201);
+ *     res.send(404);
+ *
+ * @param {String|Object|Number|Buffer} body or status
+ * @param {Object|Number} headers or status
+ * @param {Number} status
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.send = function(body, headers, status){
+  // allow status as second arg
+  if ('number' == typeof headers) {
+    status = headers,
+    headers = null;
+  }
+
+  // default status
+  status = status || this.statusCode;
+
+  // allow 0 args as 204
+  if (!arguments.length || undefined === body) status = 204;
+
+  // determine content type
+  switch (typeof body) {
+    case 'number':
+      if (!this.header('Content-Type')) {
+        this.contentType('.txt');
+      }
+      body = http.STATUS_CODES[status = body];
+      break;
+    case 'string':
+      if (!this.header('Content-Type')) {
+        this.charset = this.charset || 'utf-8';
+        this.contentType('.html');
+      }
+      break;
+    case 'boolean':
+    case 'object':
+      if (Buffer.isBuffer(body)) {
+        if (!this.header('Content-Type')) {
+          this.contentType('.bin');
+        }
+      } else {
+        return this.json(body, headers, status);
+      }
+      break;
+  }
+
+  // populate Content-Length
+  if (undefined !== body && !this.header('Content-Length')) {
+    this.header('Content-Length', Buffer.isBuffer(body)
+      ? body.length
+      : Buffer.byteLength(body));
+  }
+
+  // merge headers passed
+  if (headers) {
+    var fields = Object.keys(headers);
+    for (var i = 0, len = fields.length; i < len; ++i) {
+      var field = fields[i];
+      this.header(field, headers[field]);
+    }
+  }
+
+  // strip irrelevant headers
+  if (204 == status || 304 == status) {
+    this.removeHeader('Content-Type');
+    this.removeHeader('Content-Length');
+    body = '';
+  }
+
+  // respond
+  this.statusCode = status;
+  this.end('HEAD' == this.req.method ? null : body);
+  return this;
+};
+
+/**
+ * Send JSON response with `obj`, optional `headers`, and optional `status`.
+ *
+ * Examples:
+ *
+ *     res.json(null);
+ *     res.json({ user: 'tj' });
+ *     res.json('oh noes!', 500);
+ *     res.json('I dont have that', 404);
+ *
+ * @param {Mixed} obj
+ * @param {Object|Number} headers or status
+ * @param {Number} status
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.json = function(obj, headers, status){
+  var body = JSON.stringify(obj)
+    , callback = this.req.query.callback
+    , jsonp = this.app.enabled('jsonp callback');
+
+  this.charset = this.charset || 'utf-8';
+  this.header('Content-Type', 'application/json');
+
+  if (callback && jsonp) {
+    this.header('Content-Type', 'text/javascript');
+    body = callback.replace(/[^\w$.]/g, '') + '(' + body + ');';
+  }
+
+  return this.send(body, headers, status);
+};
+
+/**
+ * Set status `code`.
+ *
+ * @param {Number} code
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.status = function(code){
+  this.statusCode = code;
+  return this;
+};
+
+/**
+ * Transfer the file at the given `path`. Automatically sets 
+ * the _Content-Type_ response header field. `next()` is called
+ * when `path` is a directory, or when an error occurs.
+ *
+ * Options:
+ *
+ *   - `maxAge` defaulting to 0
+ *   - `root`   root directory for relative filenames
+ *
+ * @param {String} path
+ * @param {Object|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.sendfile = function(path, options, fn){
+  var next = this.req.next;
+  options = options || {};
+
+  // support function as second arg
+  if ('function' == typeof options) {
+    fn = options;
+    options = {};
+  }
+
+  options.path = encodeURIComponent(path);
+  options.callback = fn;
+  send(this.req, this, next, options);
+};
+
+/**
+ * Set _Content-Type_ response header passed through `mime.lookup()`.
+ *
+ * Examples:
+ *
+ *     var filename = 'path/to/image.png';
+ *     res.contentType(filename);
+ *     // res.headers['Content-Type'] is now "image/png"
+ *
+ *     res.contentType('.html');
+ *     res.contentType('html');
+ *     res.contentType('json');
+ *     res.contentType('png');
+ *
+ * @param {String} type
+ * @return {String} the resolved mime type
+ * @api public
+ */
+
+res.contentType = function(type){
+  return this.header('Content-Type', mime.lookup(type));
+};
+
+/**
+ * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
+ *
+ * @param {String} filename
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.attachment = function(filename){
+  if (filename) this.contentType(filename);
+  this.header('Content-Disposition', filename
+    ? 'attachment; filename="' + basename(filename) + '"'
+    : 'attachment');
+  return this;
+};
+
+/**
+ * Transfer the file at the given `path`, with optional 
+ * `filename` as an attachment and optional callback `fn(err)`,
+ * and optional `fn2(err)` which is invoked when an error has
+ * occurred after header has been sent.
+ *
+ * @param {String} path
+ * @param {String|Function} filename or fn
+ * @param {Function} fn
+ * @param {Function} fn2
+ * @api public
+ */
+
+res.download = function(path, filename, fn, fn2){
+  var self = this;
+
+  // support callback as second arg
+  if ('function' == typeof filename) {
+    fn2 = fn;
+    fn = filename;
+    filename = null;
+  }
+
+  // transfer the file
+  this.attachment(filename || path).sendfile(path, function(err){
+    var sentHeader = self._header;
+    if (err) {
+      if (!sentHeader) self.removeHeader('Content-Disposition');
+      if (sentHeader) {
+        fn2 && fn2(err);
+      } else if (fn) {
+        fn(err);
+      } else {
+        self.req.next(err);
+      }
+    } else if (fn) {
+      fn();
+    }
+  });
+};
+
+/**
+ * Set or get response header `name` with optional `val`.
+ *
+ * @param {String} name
+ * @param {String} val
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.header = function(name, val){
+  if (1 == arguments.length) return this.getHeader(name);
+  this.setHeader(name, val);
+  return this;
+};
+
+/**
+ * Clear cookie `name`.
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @api public
+ */
+
+res.clearCookie = function(name, options){
+  var opts = { expires: new Date(1) };
+  this.cookie(name, '', options
+    ? utils.merge(options, opts)
+    : opts);
+};
+
+/**
+ * Set cookie `name` to `val`, with the given `options`.
+ *
+ * Options:
+ *
+ *    - `maxAge`   max-age in milliseconds, converted to `expires`
+ *    - `path`     defaults to the "basepath" setting which is typically "/"
+ *
+ * Examples:
+ *
+ *    // "Remember Me" for 15 minutes
+ *    res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
+ *
+ *    // save as above
+ *    res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
+ *
+ * @param {String} name
+ * @param {String} val
+ * @param {Options} options
+ * @api public
+ */
+
+res.cookie = function(name, val, options){
+  options = options || {};
+  if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
+  if (undefined === options.path) options.path = this.app.set('basepath');
+  var cookie = utils.serializeCookie(name, val, options);
+  this.header('Set-Cookie', cookie);
+};
+
+/**
+ * Redirect to the given `url` with optional response `status`
+ * defauling to 302.
+ *
+ * The given `url` can also be the name of a mapped url, for
+ * example by default express supports "back" which redirects
+ * to the _Referrer_ or _Referer_ headers or the application's
+ * "basepath" setting. Express also supports "basepath" out of the box,
+ * which can be set via `app.set('basepath', '/blog');`, and defaults
+ * to '/'.
+ *
+ * Redirect Mapping:
+ * 
+ *  To extend the redirect mapping capabilities that Express provides,
+ *  we may use the `app.redirect()` method:
+ * 
+ *     app.redirect('google', 'http://google.com');
+ * 
+ *  Now in a route we may call:
+ *
+ *     res.redirect('google');
+ *
+ *  We may also map dynamic redirects:
+ *
+ *      app.redirect('comments', function(req, res){
+ *          return '/post/' + req.params.id + '/comments';
+ *      });
+ *
+ *  So now we may do the following, and the redirect will dynamically adjust to
+ *  the context of the request. If we called this route with _GET /post/12_ our
+ *  redirect _Location_ would be _/post/12/comments_.
+ *
+ *      app.get('/post/:id', function(req, res){
+ *        res.redirect('comments');
+ *      });
+ *
+ *  Unless an absolute `url` is given, the app's mount-point
+ *  will be respected. For example if we redirect to `/posts`,
+ *  and our app is mounted at `/blog` we will redirect to `/blog/posts`.
+ *
+ * @param {String} url
+ * @param {Number} code
+ * @api public
+ */
+
+res.redirect = function(url, status){
+  var app = this.app
+    , req = this.req
+    , base = app.set('basepath') || app.route
+    , status = status || 302
+    , head = 'HEAD' == req.method
+    , body;
+
+  // Setup redirect map
+  var map = {
+      back: req.header('Referrer', base)
+    , home: base
+  };
+
+  // Support custom redirect map
+  map.__proto__ = app.redirects;
+
+  // Attempt mapped redirect
+  var mapped = 'function' == typeof map[url]
+    ? map[url](req, this)
+    : map[url];
+
+  // Perform redirect
+  url = mapped || url;
+
+  // Relative
+  if (!~url.indexOf('://')) {
+    // Respect mount-point
+    if ('/' != base && 0 != url.indexOf(base)) url = base + url;
+
+    // Absolute
+    var host = req.headers.host
+      , tls = req.connection.encrypted;
+    url = 'http' + (tls ? 's' : '') + '://' + host + url;
+  }
+
+  // Support text/{plain,html} by default
+  if (req.accepts('html')) {
+    body = '<p>' + http.STATUS_CODES[status] + '. Redirecting to <a href="' + url + '">' + url + '</a></p>';
+    this.header('Content-Type', 'text/html');
+  } else {
+    body = http.STATUS_CODES[status] + '. Redirecting to ' + url;
+    this.header('Content-Type', 'text/plain');
+  }
+
+  // Respond
+  this.statusCode = status;
+  this.header('Location', url);
+  this.end(head ? null : body);
+};
+
+/**
+ * Assign the view local variable `name` to `val` or return the
+ * local previously assigned to `name`.
+ *
+ * @param {String} name
+ * @param {Mixed} val
+ * @return {Mixed} val
+ * @api public
+ */
+
+res.local = function(name, val){
+  this._locals = this._locals || {};
+  return undefined === val
+    ? this._locals[name]
+    : this._locals[name] = val;
+};
+
+/**
+ * Assign several locals with the given `obj`,
+ * or return the locals.
+ *
+ * @param {Object} obj
+ * @return {Object|Undefined}
+ * @api public
+ */
+
+res.locals =
+res.helpers = function(obj){
+  if (obj) {
+    for (var key in obj) {
+      this.local(key, obj[key]);
+    }
+  } else {
+    return this._locals;
+  }
+};
diff --git a/weinre.server/node_modules/express/lib/router/collection.js b/weinre.server/node_modules/express/lib/router/collection.js
new file mode 100644
index 0000000..991a9a2
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/router/collection.js
@@ -0,0 +1,53 @@
+
+/*!
+ * Express - router - Collection
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Collection`.
+ */
+
+module.exports = Collection;
+
+/**
+ * Initialize a new route `Collection`
+ * with the given `router`.
+ * 
+ * @param {Router} router
+ * @api private
+ */
+
+function Collection(router) {
+  Array.apply(this, arguments);
+  this.router = router;
+}
+
+/**
+ * Inherit from `Array.prototype`.
+ */
+
+Collection.prototype.__proto__ = Array.prototype;
+
+/**
+ * Remove the routes in this collection.
+ *
+ * @return {Collection} of routes removed
+ * @api public
+ */
+
+Collection.prototype.remove = function(){
+  var router = this.router
+    , len = this.length
+    , ret = new Collection(this.router);
+
+  for (var i = 0; i < len; ++i) {
+    if (router.remove(this[i])) {
+      ret.push(this[i]);
+    }
+  }
+
+  return ret;
+};
+
diff --git a/weinre.server/node_modules/express/lib/router/index.js b/weinre.server/node_modules/express/lib/router/index.js
new file mode 100644
index 0000000..ff1498b
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/router/index.js
@@ -0,0 +1,398 @@
+
+/*!
+ * Express - Router
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Route = require('./route')
+  , Collection = require('./collection')
+  , utils = require('../utils')
+  , parse = require('url').parse
+  , toArray = utils.toArray;
+
+/**
+ * Expose `Router` constructor.
+ */
+
+exports = module.exports = Router;
+
+/**
+ * Expose HTTP methods.
+ */
+
+var methods = exports.methods = require('./methods');
+
+/**
+ * Initialize a new `Router` with the given `app`.
+ * 
+ * @param {express.HTTPServer} app
+ * @api private
+ */
+
+function Router(app) {
+  var self = this;
+  this.app = app;
+  this.routes = {};
+  this.params = {};
+  this._params = [];
+
+  this.middleware = function(req, res, next){
+    self._dispatch(req, res, next);
+  };
+}
+
+/**
+ * Register a param callback `fn` for the given `name`.
+ *
+ * @param {String|Function} name
+ * @param {Function} fn
+ * @return {Router} for chaining
+ * @api public
+ */
+
+Router.prototype.param = function(name, fn){
+  // param logic
+  if ('function' == typeof name) {
+    this._params.push(name);
+    return;
+  }
+
+  // apply param functions
+  var params = this._params
+    , len = params.length
+    , ret;
+
+  for (var i = 0; i < len; ++i) {
+    if (ret = params[i](name, fn)) {
+      fn = ret;
+    }
+  }
+
+  // ensure we end up with a
+  // middleware function
+  if ('function' != typeof fn) {
+    throw new Error('invalid param() call for ' + name + ', got ' + fn);
+  }
+
+  (this.params[name] = this.params[name] || []).push(fn);
+  return this;
+};
+
+/**
+ * Return a `Collection` of all routes defined.
+ *
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.all = function(){
+  return this.find(function(){
+    return true;
+  });
+};
+
+/**
+ * Remove the given `route`, returns
+ * a bool indicating if the route was present
+ * or not.
+ *
+ * @param {Route} route
+ * @return {Boolean}
+ * @api public
+ */
+
+Router.prototype.remove = function(route){
+  var routes = this.routes[route.method]
+    , len = routes.length;
+
+  for (var i = 0; i < len; ++i) {
+    if (route == routes[i]) {
+      routes.splice(i, 1);
+      return true;
+    }
+  }
+};
+
+/**
+ * Return routes with route paths matching `path`.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.lookup = function(method, path){
+  return this.find(function(route){
+    return path == route.path
+      && (route.method == method
+      || method == 'all');
+  });
+};
+
+/**
+ * Return routes with regexps that match the given `url`.
+ *
+ * @param {String} method
+ * @param {String} url
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.match = function(method, url){
+  return this.find(function(route){
+    return route.match(url)
+      && (route.method == method
+      || method == 'all');
+  });
+};
+
+/**
+ * Find routes based on the return value of `fn`
+ * which is invoked once per route.
+ *
+ * @param {Function} fn
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.find = function(fn){
+  var len = methods.length
+    , ret = new Collection(this)
+    , method
+    , routes
+    , route;
+
+  for (var i = 0; i < len; ++i) {
+    method = methods[i];
+    routes = this.routes[method];
+    if (!routes) continue;
+    for (var j = 0, jlen = routes.length; j < jlen; ++j) {
+      route = routes[j];
+      if (fn(route)) ret.push(route);
+    }
+  }
+
+  return ret;
+};
+
+/**
+ * Route dispatcher aka the route "middleware".
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @param {Function} next
+ * @api private
+ */
+
+Router.prototype._dispatch = function(req, res, next){
+  var params = this.params
+    , self = this;
+
+  // route dispatch
+  (function pass(i, err){
+    var paramCallbacks
+      , paramIndex = 0
+      , paramVal
+      , route
+      , keys
+      , key
+      , ret;
+
+    // match next route
+    function nextRoute(err) {
+      pass(req._route_index + 1, err);
+    }
+
+    // match route
+    req.route = route = self._match(req, i);
+
+    // implied OPTIONS
+    if (!route && 'OPTIONS' == req.method) return self._options(req, res);
+
+    // no route
+    if (!route) return next(err);
+
+    // we have a route
+    // start at param 0
+    req.params = route.params;
+    keys = route.keys;
+    i = 0;
+
+    // param callbacks
+    function param(err) {
+      paramIndex = 0;
+      key = keys[i++];
+      paramVal = key && req.params[key.name];
+      paramCallbacks = key && params[key.name];
+
+      try {
+        if ('route' == err) {
+          nextRoute();
+        } else if (err) {
+          i = 0;
+          callbacks(err);
+        } else if (paramCallbacks && undefined !== paramVal) {
+          paramCallback();
+        } else if (key) {
+          param();
+        } else {
+          i = 0;
+          callbacks();
+        }
+      } catch (err) {
+        param(err);
+      }
+    };
+
+    param(err);
+    
+    // single param callbacks
+    function paramCallback(err) {
+      var fn = paramCallbacks[paramIndex++];
+      if (err || !fn) return param(err);
+      fn(req, res, paramCallback, paramVal, key.name);
+    }
+
+    // invoke route callbacks
+    function callbacks(err) {
+      var fn = route.callbacks[i++];
+      try {
+        if ('route' == err) {
+          nextRoute();
+        } else if (err && fn) {
+          if (fn.length < 4) return callbacks(err);
+          fn(err, req, res, callbacks);
+        } else if (fn) {
+          fn(req, res, callbacks);
+        } else {
+          nextRoute(err);
+        }
+      } catch (err) {
+        callbacks(err);
+      }
+    }
+  })(0);
+};
+
+/**
+ * Respond to __OPTIONS__ method.
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+Router.prototype._options = function(req, res){
+  var path = parse(req.url).pathname
+    , body = this._optionsFor(path).join(',');
+  res.send(body, { Allow: body });
+};
+
+/**
+ * Return an array of HTTP verbs or "options" for `path`.
+ *
+ * @param {String} path
+ * @return {Array}
+ * @api private
+ */
+
+Router.prototype._optionsFor = function(path){
+  var self = this;
+  return methods.filter(function(method){
+    var routes = self.routes[method];
+    if (!routes || 'options' == method) return;
+    for (var i = 0, len = routes.length; i < len; ++i) {
+      if (routes[i].match(path)) return true;
+    }
+  }).map(function(method){
+    return method.toUpperCase();
+  });
+};
+
+/**
+ * Attempt to match a route for `req`
+ * starting from offset `i`.
+ *
+ * @param {IncomingMessage} req
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype._match = function(req, i){
+  var method = req.method.toLowerCase()
+    , url = parse(req.url)
+    , path = url.pathname
+    , routes = this.routes
+    , captures
+    , route
+    , keys;
+
+  // pass HEAD to GET routes
+  if ('head' == method) method = 'get';
+
+  // routes for this method
+  if (routes = routes[method]) {
+
+    // matching routes
+    for (var len = routes.length; i < len; ++i) {
+      route = routes[i];
+      if (captures = route.match(path)) {
+        keys = route.keys;
+        route.params = [];
+
+        // params from capture groups
+        for (var j = 1, jlen = captures.length; j < jlen; ++j) {
+          var key = keys[j-1]
+            , val = 'string' == typeof captures[j]
+              ? decodeURIComponent(captures[j])
+              : captures[j];
+          if (key) {
+            route.params[key.name] = val;
+          } else {
+            route.params.push(val);
+          }
+        }
+
+        // all done
+        req._route_index = i;
+        return route;
+      }
+    }
+  }
+};
+
+/**
+ * Route `method`, `path`, and one or more callbacks.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Function} callback...
+ * @return {Router} for chaining
+ * @api private
+ */
+
+Router.prototype._route = function(method, path, callbacks){
+  var app = this.app
+    , callbacks = utils.flatten(toArray(arguments, 2));
+
+  // ensure path was given
+  if (!path) throw new Error('app.' + method + '() requires a path');
+
+  // create the route
+  var route = new Route(method, path, callbacks, {
+      sensitive: app.enabled('case sensitive routes')
+    , strict: app.enabled('strict routing')
+  });
+
+  // add it
+  (this.routes[method] = this.routes[method] || [])
+    .push(route);
+  return this;
+};
diff --git a/weinre.server/node_modules/express/lib/router/methods.js b/weinre.server/node_modules/express/lib/router/methods.js
new file mode 100644
index 0000000..e19787b
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/router/methods.js
@@ -0,0 +1,70 @@
+
+/*!
+ * Express - router - methods
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Hypertext Transfer Protocol -- HTTP/1.1 
+ * http://www.ietf.org/rfc/rfc2616.txt
+ */
+
+var RFC2616 = ['OPTIONS', 'GET', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];
+
+/**
+ * HTTP Extensions for Distributed Authoring -- WEBDAV
+ * http://www.ietf.org/rfc/rfc2518.txt
+ */
+
+var RFC2518 = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'];
+
+/**
+ * Versioning Extensions to WebDAV 
+ * http://www.ietf.org/rfc/rfc3253.txt
+ */
+
+var RFC3253 = ['VERSION-CONTROL', 'REPORT', 'CHECKOUT', 'CHECKIN', 'UNCHECKOUT', 'MKWORKSPACE', 'UPDATE', 'LABEL', 'MERGE', 'BASELINE-CONTROL', 'MKACTIVITY'];
+
+/**
+ * Ordered Collections Protocol (WebDAV) 
+ * http://www.ietf.org/rfc/rfc3648.txt
+ */
+
+var RFC3648 = ['ORDERPATCH'];
+
+/**
+ * Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol 
+ * http://www.ietf.org/rfc/rfc3744.txt
+ */
+
+var RFC3744 = ['ACL'];
+
+/**
+ * Web Distributed Authoring and Versioning (WebDAV) SEARCH
+ * http://www.ietf.org/rfc/rfc5323.txt
+ */
+
+var RFC5323 = ['SEARCH'];
+
+/**
+ * PATCH Method for HTTP 
+ * http://www.ietf.org/rfc/rfc5789.txt
+ */
+
+var RFC5789 = ['PATCH'];
+
+/**
+ * Expose the methods.
+ */
+
+module.exports = [].concat(
+    RFC2616
+  , RFC2518
+  , RFC3253
+  , RFC3648
+  , RFC3744
+  , RFC5323
+  , RFC5789).map(function(method){
+    return method.toLowerCase();
+  });
diff --git a/weinre.server/node_modules/express/lib/router/route.js b/weinre.server/node_modules/express/lib/router/route.js
new file mode 100644
index 0000000..7f2965c
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/router/route.js
@@ -0,0 +1,88 @@
+
+/*!
+ * Express - router - Route
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Route`.
+ */
+
+module.exports = Route;
+
+/**
+ * Initialize `Route` with the given HTTP `method`, `path`,
+ * and an array of `callbacks` and `options`.
+ *
+ * Options:
+ *
+ *   - `sensitive`    enable case-sensitive routes
+ *   - `strict`       enable strict matching for trailing slashes
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Array} callbacks
+ * @param {Object} options.
+ * @api private
+ */
+
+function Route(method, path, callbacks, options) {
+  options = options || {};
+  this.path = path;
+  this.method = method;
+  this.callbacks = callbacks;
+  this.regexp = normalize(path
+    , this.keys = []
+    , options.sensitive
+    , options.strict);
+}
+
+/**
+ * Check if this route matches `path` and return captures made.
+ *
+ * @param {String} path
+ * @return {Array}
+ * @api private
+ */
+
+Route.prototype.match = function(path){
+  return this.regexp.exec(path);
+};
+
+/**
+ * Normalize the given path string,
+ * returning a regular expression.
+ *
+ * An empty array should be passed,
+ * which will contain the placeholder
+ * key names. For example "/user/:id" will
+ * then contain ["id"].
+ *
+ * @param  {String|RegExp} path
+ * @param  {Array} keys
+ * @param  {Boolean} sensitive
+ * @param  {Boolean} strict
+ * @return {RegExp}
+ * @api private
+ */
+
+function normalize(path, keys, sensitive, strict) {
+  if (path instanceof RegExp) return path;
+  path = path
+    .concat(strict ? '' : '/?')
+    .replace(/\/\(/g, '(?:/')
+    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
+      keys.push({ name: key, optional: !! optional });
+      slash = slash || '';
+      return ''
+        + (optional ? '' : slash)
+        + '(?:'
+        + (optional ? slash : '')
+        + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
+        + (optional || '');
+    })
+    .replace(/([\/.])/g, '\\$1')
+    .replace(/\*/g, '(.*)');
+  return new RegExp('^' + path + '$', sensitive ? '' : 'i');
+}
diff --git a/weinre.server/node_modules/express/lib/utils.js b/weinre.server/node_modules/express/lib/utils.js
new file mode 100644
index 0000000..d579f7c
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/utils.js
@@ -0,0 +1,152 @@
+
+/*!
+ * Express - Utils
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Check if `path` looks absolute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.isAbsolute = function(path){
+  if ('/' == path[0]) return true;
+  if (':' == path[1] && '\\' == path[2]) return true;
+};
+
+/**
+ * Merge object `b` with `a` giving precedence to
+ * values in object `a`.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object} a
+ * @api private
+ */
+
+exports.union = function(a, b){
+  if (a && b) {
+    var keys = Object.keys(b)
+      , len = keys.length
+      , key;
+    for (var i = 0; i < len; ++i) {
+      key = keys[i];
+      if (!a.hasOwnProperty(key)) {
+        a[key] = b[key];
+      }
+    }
+  }
+  return a;
+};
+
+/**
+ * Flatten the given `arr`.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.flatten = function(arr, ret){
+  var ret = ret || []
+    , len = arr.length;
+  for (var i = 0; i < len; ++i) {
+    if (Array.isArray(arr[i])) {
+      exports.flatten(arr[i], ret);
+    } else {
+      ret.push(arr[i]);
+    }
+  }
+  return ret;
+};
+
+/**
+ * Parse mini markdown implementation.
+ * The following conversions are supported,
+ * primarily for the "flash" middleware:
+ *
+ *    _foo_ or *foo* become <em>foo</em>
+ *    __foo__ or **foo** become <strong>foo</strong>
+ *    [A](B) becomes <a href="B">A</a>
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.miniMarkdown = function(str){
+  return String(str)
+    .replace(/(__|\*\*)(.*?)\1/g, '<strong>$2</strong>')
+    .replace(/(_|\*)(.*?)\1/g, '<em>$2</em>')
+    .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
+};
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param  {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html) {
+  return String(html)
+    .replace(/&/g, '&amp;')
+    .replace(/"/g, '&quot;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;');
+};
+
+/**
+ * Parse "Range" header `str` relative to the given file `size`.
+ *
+ * @param {Number} size
+ * @param {String} str
+ * @return {Array}
+ * @api private
+ */
+
+exports.parseRange = function(size, str){
+  var valid = true;
+  var arr = str.substr(6).split(',').map(function(range){
+    var range = range.split('-')
+      , start = parseInt(range[0], 10)
+      , end = parseInt(range[1], 10);
+
+    // -500
+    if (isNaN(start)) {
+      start = size - end;
+      end = size - 1;
+    // 500-
+    } else if (isNaN(end)) {
+      end = size - 1;
+    }
+
+    // Invalid
+    if (isNaN(start) || isNaN(end) || start > end) valid = false;
+
+    return { start: start, end: end };
+  });
+  return valid ? arr : undefined;
+};
+
+/**
+ * Fast alternative to `Array.prototype.slice.call()`.
+ *
+ * @param {Arguments} args
+ * @param {Number} n
+ * @return {Array}
+ * @api public
+ */
+
+exports.toArray = function(args, i){
+  var arr = []
+    , len = args.length
+    , i = i || 0;
+  for (; i < len; ++i) arr.push(args[i]);
+  return arr;
+};
diff --git a/weinre.server/node_modules/express/lib/view.js b/weinre.server/node_modules/express/lib/view.js
new file mode 100644
index 0000000..5258249
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/view.js
@@ -0,0 +1,460 @@
+
+/*!
+ * Express - view
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+  , extname = path.extname
+  , dirname = path.dirname
+  , basename = path.basename
+  , utils = require('connect').utils
+  , View = require('./view/view')
+  , partial = require('./view/partial')
+  , union = require('./utils').union
+  , merge = utils.merge
+  , http = require('http')
+  , res = http.ServerResponse.prototype;
+
+/**
+ * Expose constructors.
+ */
+
+exports = module.exports = View;
+
+/**
+ * Export template engine registrar.
+ */
+
+exports.register = View.register;
+
+/**
+ * Lookup and compile `view` with cache support by supplying
+ * both the `cache` object and `cid` string,
+ * followed by `options` passed to `exports.lookup()`.
+ *
+ * @param {String} view
+ * @param {Object} cache
+ * @param {Object} cid
+ * @param {Object} options
+ * @return {View}
+ * @api private
+ */
+
+exports.compile = function(view, cache, cid, options){
+  if (cache && cid && cache[cid]){
+    options.filename = cache[cid].path;
+    return cache[cid];
+  }
+
+  // lookup
+  view = exports.lookup(view, options);
+
+  // hints
+  if (!view.exists) {
+    if (options.hint) hintAtViewPaths(view.original, options);
+    var err = new Error('failed to locate view "' + view.original.view + '"');
+    err.view = view.original;
+    throw err;
+  }
+
+  // compile
+  options.filename = view.path;
+  view.fn = view.templateEngine.compile(view.contents, options);
+  cache[cid] = view;
+
+  return view;
+};
+
+/**
+ * Lookup `view`, returning an instanceof `View`.
+ *
+ * Options:
+ *
+ *   - `root` root directory path
+ *   - `defaultEngine` default template engine
+ *   - `parentView` parent `View` object
+ *   - `cache` cache object
+ *   - `cacheid` optional cache id
+ *
+ * Lookup:
+ *
+ *   - partial `_<name>`
+ *   - any `<name>/index`
+ *   - non-layout `../<name>/index`
+ *   - any `<root>/<name>`
+ *   - partial `<root>/_<name>`
+ *
+ * @param {String} view
+ * @param {Object} options
+ * @return {View}
+ * @api private
+ */
+
+exports.lookup = function(view, options){
+  var orig = view = new View(view, options)
+    , partial = options.isPartial
+    , layout = options.isLayout;
+
+  // Try _ prefix ex: ./views/_<name>.jade
+  // taking precedence over the direct path
+  if (partial) {
+    view = new View(orig.prefixPath, options);
+    if (!view.exists) view = orig;
+  }
+
+  // Try index ex: ./views/user/index.jade
+  if (!layout && !view.exists) view = new View(orig.indexPath, options);
+
+  // Try ../<name>/index ex: ../user/index.jade
+  // when calling partial('user') within the same dir
+  if (!layout && !view.exists) view = new View(orig.upIndexPath, options);
+
+  // Try root ex: <root>/user.jade
+  if (!view.exists) view = new View(orig.rootPath, options);
+
+  // Try root _ prefix ex: <root>/_user.jade
+  if (!view.exists && partial) view = new View(view.prefixPath, options);
+
+  view.original = orig;
+  return view;
+};
+
+/**
+ * Partial render helper.
+ *
+ * @api private
+ */
+
+function renderPartial(res, view, options, parentLocals, parent){
+  var collection, object, locals;
+
+  if (options) {
+    // collection
+    if (options.collection) {
+      collection = options.collection;
+      delete options.collection;
+    } else if ('length' in options) {
+      collection = options;
+      options = {};
+    }
+
+    // locals
+    if (options.locals) {
+      locals = options.locals;
+      delete options.locals;
+    }
+
+    // object
+    if ('Object' != options.constructor.name) {
+      object = options;
+      options = {};
+    } else if (undefined != options.object) {
+      object = options.object;
+      delete options.object;
+    }
+  } else {
+    options = {};
+  }
+
+  // Inherit locals from parent
+  union(options, parentLocals);
+
+  // Merge locals
+  if (locals) merge(options, locals);
+
+  // Partials dont need layouts
+  options.isPartial = true;
+  options.layout = false;
+
+  // Deduce name from view path
+  var name = options.as || partial.resolveObjectName(view);
+
+  // Render partial
+  function render(){
+    if (object) {
+      if ('string' == typeof name) {
+        options[name] = object;
+      } else if (name === global) {
+        merge(options, object);
+      }
+    }
+    return res.render(view, options, null, parent, true);
+  }
+
+  // Collection support
+  if (collection) {
+    var len = collection.length
+      , buf = ''
+      , keys
+      , key
+      , val;
+
+    options.collectionLength = len;
+
+    if ('number' == typeof len || Array.isArray(collection)) {
+      for (var i = 0; i < len; ++i) {
+        val = collection[i];
+        options.firstInCollection = i == 0;
+        options.indexInCollection = i;
+        options.lastInCollection = i == len - 1;
+        object = val;
+        buf += render();
+      }
+    } else {
+      keys = Object.keys(collection);
+      len = keys.length;
+      options.collectionLength = len;
+      options.collectionKeys = keys;
+      for (var i = 0; i < len; ++i) {
+        key = keys[i];
+        val = collection[key];
+        options.keyInCollection = key;
+        options.firstInCollection = i == 0;
+        options.indexInCollection = i;
+        options.lastInCollection = i == len - 1;
+        object = val;
+        buf += render();
+      }
+    }
+
+    return buf;
+  } else {
+    return render();
+  }
+};
+
+/**
+ * Render `view` partial with the given `options`. Optionally a
+ * callback `fn(err, str)` may be passed instead of writing to
+ * the socket.
+ *
+ * Options:
+ *
+ *   - `object` Single object with name derived from the view (unless `as` is present)
+ *
+ *   - `as` Variable name for each `collection` value, defaults to the view name.
+ *     * as: 'something' will add the `something` local variable
+ *     * as: this will use the collection value as the template context
+ *     * as: global will merge the collection value's properties with `locals`
+ *
+ *   - `collection` Array of objects, the name is derived from the view name itself.
+ *     For example _video.html_ will have a object _video_ available to it.
+ *
+ * @param  {String} view
+ * @param  {Object|Array|Function} options, collection, callback, or object
+ * @param  {Function} fn
+ * @return {String}
+ * @api public
+ */
+
+res.partial = function(view, options, fn){
+  var app = this.app
+    , options = options || {}
+    , viewEngine = app.set('view engine')
+    , parent = {};
+
+  // accept callback as second argument
+  if ('function' == typeof options) {
+    fn = options;
+    options = {};
+  }
+
+  // root "views" option
+  parent.dirname = app.set('views') || process.cwd() + '/views';
+
+  // utilize "view engine" option
+  if (viewEngine) parent.engine = viewEngine;
+
+  // render the partial
+  try {
+    var str = renderPartial(this, view, options, null, parent);
+  } catch (err) {
+    if (fn) {
+      fn(err);
+    } else {
+      this.req.next(err);
+    }
+    return;
+  }
+
+  // callback or transfer
+  if (fn) {
+    fn(null, str);
+  } else {
+    this.send(str);
+  }
+};
+
+/**
+ * Render `view` with the given `options` and optional callback `fn`.
+ * When a callback function is given a response will _not_ be made
+ * automatically, however otherwise a response of _200_ and _text/html_ is given.
+ *
+ * Options:
+ *
+ *  - `scope`     Template evaluation context (the value of `this`)
+ *  - `debug`     Output debugging information
+ *  - `status`    Response status code
+ *
+ * @param  {String} view
+ * @param  {Object|Function} options or callback function
+ * @param  {Function} fn
+ * @api public
+ */
+
+res.render = function(view, opts, fn, parent, sub){
+  // support callback function as second arg
+  if ('function' == typeof opts) {
+    fn = opts, opts = null;
+  }
+
+  try {
+    return this._render(view, opts, fn, parent, sub);
+  } catch (err) {
+    // callback given
+    if (fn) {
+      fn(err);
+    // unwind to root call to prevent multiple callbacks
+    } else if (sub) {
+      throw err;
+    // root template, next(err)
+    } else {
+      this.req.next(err);
+    }
+  }
+};
+
+// private render()
+
+res._render = function(view, opts, fn, parent, sub){
+  var options = {}
+    , self = this
+    , app = this.app
+    , helpers = app._locals
+    , dynamicHelpers = app.dynamicViewHelpers
+    , viewOptions = app.set('view options')
+    , root = app.set('views') || process.cwd() + '/views';
+
+  // cache id
+  var cid = app.enabled('view cache')
+    ? view + (parent ? ':' + parent.path : '')
+    : false;
+
+  // merge "view options"
+  if (viewOptions) merge(options, viewOptions);
+
+  // merge res._locals
+  if (this._locals) merge(options, this._locals);
+
+  // merge render() options
+  if (opts) merge(options, opts);
+
+  // merge render() .locals
+  if (opts && opts.locals) merge(options, opts.locals);
+
+  // status support
+  if (options.status) this.statusCode = options.status;
+
+  // capture attempts
+  options.attempts = [];
+
+  var partial = options.isPartial
+    , layout = options.layout;
+
+  // Layout support
+  if (true === layout || undefined === layout) {
+    layout = 'layout';
+  }
+
+  // Default execution scope to a plain object
+  options.scope = options.scope || {};
+
+  // Populate view
+  options.parentView = parent;
+
+  // "views" setting
+  options.root = root;
+
+  // "view engine" setting
+  options.defaultEngine = app.set('view engine');
+
+  // charset option
+  if (options.charset) this.charset = options.charset;
+
+  // Dynamic helper support
+  if (false !== options.dynamicHelpers) {
+    // cache
+    if (!this.__dynamicHelpers) {
+      this.__dynamicHelpers = {};
+      for (var key in dynamicHelpers) {
+        this.__dynamicHelpers[key] = dynamicHelpers[key].call(
+            this.app
+          , this.req
+          , this);
+      }
+    }
+
+    // apply
+    merge(options, this.__dynamicHelpers);
+  }
+
+  // Merge view helpers
+  union(options, helpers);
+
+  // Always expose partial() as a local
+  options.partial = function(path, opts){
+    return renderPartial(self, path, opts, options, view);
+  };
+
+  // View lookup
+  options.hint = app.enabled('hints');
+  view = exports.compile(view, app.cache, cid, options);
+
+  // layout helper
+  options.layout = function(path){
+    layout = path;
+  };
+
+  // render
+  var str = view.fn.call(options.scope, options);
+
+  // layout expected
+  if (layout) {
+    options.isLayout = true;
+    options.layout = false;
+    options.body = str;
+    this.render(layout, options, fn, view, true);
+  // partial return
+  } else if (partial) {
+    return str;
+  // render complete, and
+  // callback given
+  } else if (fn) {
+    fn(null, str);
+  // respond
+  } else {
+    this.send(str);
+  }
+}
+
+/**
+ * Hint at view path resolution, outputting the
+ * paths that Express has tried.
+ *
+ * @api private
+ */
+
+function hintAtViewPaths(view, options) {
+  console.error();
+  console.error('failed to locate view "' + view.view + '", tried:');
+  options.attempts.forEach(function(path){
+    console.error('  - %s', path);
+  });
+  console.error();
+}
diff --git a/weinre.server/node_modules/express/lib/view/partial.js b/weinre.server/node_modules/express/lib/view/partial.js
new file mode 100644
index 0000000..7d2f69b
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/view/partial.js
@@ -0,0 +1,40 @@
+
+/*!
+ * Express - view - Partial
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Memory cache.
+ */
+
+var cache = {};
+
+/**
+ * Resolve partial object name from the view path.
+ *
+ * Examples:
+ *
+ *   "user.ejs" becomes "user"
+ *   "forum thread.ejs" becomes "forumThread"
+ *   "forum/thread/post.ejs" becomes "post"
+ *   "blog-post.ejs" becomes "blogPost"
+ *
+ * @return {String}
+ * @api private
+ */
+
+exports.resolveObjectName = function(view){
+  return cache[view] || (cache[view] = view
+    .split('/')
+    .slice(-1)[0]
+    .split('.')[0]
+    .replace(/^_/, '')
+    .replace(/[^a-zA-Z0-9 ]+/g, ' ')
+    .split(/ +/).map(function(word, i){
+      return i
+        ? word[0].toUpperCase() + word.substr(1)
+        : word;
+    }).join(''));
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/lib/view/view.js b/weinre.server/node_modules/express/lib/view/view.js
new file mode 100644
index 0000000..7d9392c
--- /dev/null
+++ b/weinre.server/node_modules/express/lib/view/view.js
@@ -0,0 +1,210 @@
+
+/*!
+ * Express - View
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+  , utils = require('../utils')
+  , extname = path.extname
+  , dirname = path.dirname
+  , basename = path.basename
+  , fs = require('fs')
+  , stat = fs.statSync;
+
+/**
+ * Expose `View`.
+ */
+
+exports = module.exports = View;
+
+/**
+ * Require cache.
+ */
+
+var cache = {};
+
+/**
+ * Initialize a new `View` with the given `view` path and `options`.
+ *
+ * @param {String} view
+ * @param {Object} options
+ * @api private
+ */
+
+function View(view, options) {
+  options = options || {};
+  this.view = view;
+  this.root = options.root;
+  this.relative = false !== options.relative;
+  this.defaultEngine = options.defaultEngine;
+  this.parent = options.parentView;
+  this.basename = basename(view);
+  this.engine = this.resolveEngine();
+  this.extension = '.' + this.engine;
+  this.name = this.basename.replace(this.extension, '');
+  this.path = this.resolvePath();
+  this.dirname = dirname(this.path);
+  if (options.attempts) {
+    if (!~options.attempts.indexOf(this.path))
+      options.attempts.push(this.path);
+  }
+};
+
+/**
+ * Check if the view path exists.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('exists', function(){
+  try {
+    stat(this.path);
+    return true;
+  } catch (err) {
+    return false;
+  }
+});
+
+/**
+ * Resolve view engine.
+ *
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.resolveEngine = function(){
+  // Explicit
+  if (~this.basename.indexOf('.')) return extname(this.basename).substr(1);
+  // Inherit from parent
+  if (this.parent) return this.parent.engine;
+  // Default
+  return this.defaultEngine;
+};
+
+/**
+ * Resolve view path.
+ *
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.resolvePath = function(){
+  var path = this.view;
+  // Implicit engine
+  if (!~this.basename.indexOf('.')) path += this.extension;
+  // Absolute
+  if (utils.isAbsolute(path)) return path;
+  // Relative to parent
+  if (this.relative && this.parent) return this.parent.dirname + '/' + path;
+  // Relative to root
+  return this.root
+    ? this.root + '/' + path
+    : path;
+};
+
+/**
+ * Get view contents. This is a one-time hit, so we
+ * can afford to be sync.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('contents', function(){
+  return fs.readFileSync(this.path, 'utf8');
+});
+
+/**
+ * Get template engine api, cache exports to reduce
+ * require() calls.
+ *
+ * @return {Object}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('templateEngine', function(){
+  var ext = this.extension;
+  return cache[ext] || (cache[ext] = require(this.engine));
+});
+
+/**
+ * Return root path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('rootPath', function(){
+  this.relative = false;
+  return this.resolvePath();
+});
+
+/**
+ * Return index path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('indexPath', function(){
+  return this.dirname
+    + '/' + this.basename.replace(this.extension, '')
+    + '/index' + this.extension;
+});
+
+/**
+ * Return ../<name>/index path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('upIndexPath', function(){
+  return this.dirname + '/../' + this.name + '/index' + this.extension;
+});
+
+/**
+ * Return _ prefix path alternative
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('prefixPath', function(){
+  return this.dirname + '/_' + this.basename;
+});
+
+/**
+ * Register the given template engine `exports`
+ * as `ext`. For example we may wish to map ".html"
+ * files to jade:
+ *
+ *    app.register('.html', require('jade'));
+ *
+ * or
+ *
+ *    app.register('html', require('jade'));
+ *
+ * This is also useful for libraries that may not
+ * match extensions correctly. For example my haml.js
+ * library is installed from npm as "hamljs" so instead
+ * of layout.hamljs, we can register the engine as ".haml":
+ *
+ *    app.register('.haml', require('haml-js'));
+ *
+ * @param {String} ext
+ * @param {Object} obj
+ * @api public
+ */
+
+exports.register = function(ext, exports) {
+  if ('.' != ext[0]) ext = '.' + ext;
+  cache[ext] = exports;
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/.npmignore b/weinre.server/node_modules/express/node_modules/connect/.npmignore
new file mode 100644
index 0000000..b04a224
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/.npmignore
@@ -0,0 +1,11 @@
+*.markdown
+*.md
+.git*
+Makefile
+benchmarks/
+docs/
+examples/
+install.sh
+support/
+test/
+.DS_Store
diff --git a/weinre.server/node_modules/express/node_modules/connect/LICENSE b/weinre.server/node_modules/express/node_modules/connect/LICENSE
new file mode 100644
index 0000000..0c5d22d
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2010 Sencha Inc.
+Copyright (c) 2011 LearnBoost
+Copyright (c) 2011 TJ Holowaychuk
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/index.js b/weinre.server/node_modules/express/node_modules/connect/index.js
new file mode 100644
index 0000000..7477048
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/connect');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/cache.js b/weinre.server/node_modules/express/node_modules/connect/lib/cache.js
new file mode 100644
index 0000000..4aa026e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/cache.js
@@ -0,0 +1,81 @@
+
+/*!
+ * Connect - Cache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Cache`.
+ */
+
+module.exports = Cache;
+
+/**
+ * LRU cache store.
+ *
+ * @param {Number} limit
+ * @api private
+ */
+
+function Cache(limit) {
+  this.store = {};
+  this.keys = [];
+  this.limit = limit;
+}
+
+/**
+ * Touch `key`, promoting the object.
+ *
+ * @param {String} key
+ * @param {Number} i
+ * @api private
+ */
+
+Cache.prototype.touch = function(key, i){
+  this.keys.splice(i,1);
+  this.keys.push(key);
+};
+
+/**
+ * Remove `key`.
+ *
+ * @param {String} key
+ * @api private
+ */
+
+Cache.prototype.remove = function(key){
+  delete this.store[key];
+};
+
+/**
+ * Get the object stored for `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.get = function(key){
+  return this.store[key];
+};
+
+/**
+ * Add a cache `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.add = function(key){
+  // initialize store
+  var len = this.keys.push(key);
+
+  // limit reached, invalid LRU
+  if (len > this.limit) this.remove(this.keys.shift());
+
+  var arr = this.store[key] = [];
+  arr.createdAt = new Date;
+  return arr;
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/connect.js b/weinre.server/node_modules/express/node_modules/connect/lib/connect.js
new file mode 100644
index 0000000..7857023
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/connect.js
@@ -0,0 +1,106 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var HTTPServer = require('./http').Server
+  , HTTPSServer = require('./https').Server
+  , fs = require('fs');
+
+// node patches
+
+require('./patch');
+
+// expose createServer() as the module
+
+exports = module.exports = createServer;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '1.8.5';
+
+/**
+ * Initialize a new `connect.HTTPServer` with the middleware
+ * passed to this function. When an object is passed _first_,
+ * we assume these are the tls options, and return a `connect.HTTPSServer`.
+ *
+ * Examples:
+ *
+ * An example HTTP server, accepting several middleware.
+ *
+ *     var server = connect.createServer(
+ *         connect.logger()
+ *       , connect.static(__dirname + '/public')
+ *     );
+ *
+ * An HTTPS server, utilizing the same middleware as above.
+ *
+ *     var server = connect.createServer(
+ *         { key: key, cert: cert }
+ *       , connect.logger()
+ *       , connect.static(__dirname + '/public')
+ *     );
+ *
+ * Alternatively with connect 1.0 we may omit `createServer()`.
+ *
+ *     connect(
+ *         connect.logger()
+ *       , connect.static(__dirname + '/public')
+ *     ).listen(3000);
+ *
+ * @param  {Object|Function} ...
+ * @return {Server}
+ * @api public
+ */
+
+function createServer() {
+  if ('object' == typeof arguments[0]) {
+    return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1));
+  } else {
+    return new HTTPServer(Array.prototype.slice.call(arguments));
+  }
+};
+
+// support connect.createServer()
+
+exports.createServer = createServer;
+
+// auto-load getters
+
+exports.middleware = {};
+
+/**
+ * Auto-load bundled middleware with getters.
+ */
+
+fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
+  if (/\.js$/.test(filename)) {
+    var name = filename.substr(0, filename.lastIndexOf('.'));
+    exports.middleware.__defineGetter__(name, function(){
+      return require('./middleware/' + name);
+    });
+  }
+});
+
+// expose utils
+
+exports.utils = require('./utils');
+
+// expose getters as first-class exports
+
+exports.utils.merge(exports, exports.middleware);
+
+// expose constructors
+
+exports.HTTPServer = HTTPServer;
+exports.HTTPSServer = HTTPSServer;
+
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/http.js b/weinre.server/node_modules/express/node_modules/connect/lib/http.js
new file mode 100644
index 0000000..09898e2
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/http.js
@@ -0,0 +1,217 @@
+
+/*!
+ * Connect - HTTPServer
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , parse = require('url').parse
+  , assert = require('assert');
+
+// environment
+
+var env = process.env.NODE_ENV || 'development';
+
+/**
+ * Initialize a new `Server` with the given `middleware`.
+ *
+ * Examples:
+ *
+ *     var server = connect.createServer(
+ *         connect.favicon()
+ *       , connect.logger()
+ *       , connect.static(__dirname + '/public')
+ *     );
+ *
+ * @params {Array} middleware 
+ * @return {Server}
+ * @api public
+ */
+
+var Server = exports.Server = function HTTPServer(middleware) {
+  this.stack = [];
+  middleware.forEach(function(fn){
+    this.use(fn);
+  }, this);
+  http.Server.call(this, this.handle);
+};
+
+/**
+ * Inherit from `http.Server.prototype`.
+ */
+
+Server.prototype.__proto__ = http.Server.prototype;
+
+/**
+ * Utilize the given middleware `handle` to the given `route`,
+ * defaulting to _/_. This "route" is the mount-point for the
+ * middleware, when given a value other than _/_ the middleware
+ * is only effective when that segment is present in the request's
+ * pathname.
+ *
+ * For example if we were to mount a function at _/admin_, it would
+ * be invoked on _/admin_, and _/admin/settings_, however it would
+ * not be invoked for _/_, or _/posts_.
+ *
+ * This is effectively the same as passing middleware to `connect.createServer()`,
+ * however provides a progressive api.
+ *
+ * Examples:
+ *
+ *      var server = connect.createServer();
+ *      server.use(connect.favicon());
+ *      server.use(connect.logger());
+ *      server.use(connect.static(__dirname + '/public'));
+ *
+ * If we wanted to prefix static files with _/public_, we could
+ * "mount" the `static()` middleware:
+ *
+ *      server.use('/public', connect.static(__dirname + '/public'));
+ *
+ * This api is chainable, meaning the following is valid:
+ *
+ *      connect.createServer()
+ *        .use(connect.favicon())
+ *        .use(connect.logger())
+ *        .use(connect.static(__dirname + '/public'))
+ *        .listen(3000);
+ *
+ * @param {String|Function} route or handle
+ * @param {Function} handle
+ * @return {Server}
+ * @api public
+ */
+
+Server.prototype.use = function(route, handle){
+  this.route = '/';
+
+  // default route to '/'
+  if ('string' != typeof route) {
+    handle = route;
+    route = '/';
+  }
+
+  // wrap sub-apps
+  if ('function' == typeof handle.handle) {
+    var server = handle;
+    server.route = route;
+    handle = function(req, res, next) {
+      server.handle(req, res, next);
+    };
+  }
+
+  // wrap vanilla http.Servers
+  if (handle instanceof http.Server) {
+    handle = handle.listeners('request')[0];
+  }
+
+  // normalize route to not trail with slash
+  if ('/' == route[route.length - 1]) {
+    route = route.substr(0, route.length - 1);
+  }
+
+  // add the middleware
+  this.stack.push({ route: route, handle: handle });
+
+  // allow chaining
+  return this;
+};
+
+/**
+ * Handle server requests, punting them down
+ * the middleware stack.
+ *
+ * @api private
+ */
+
+Server.prototype.handle = function(req, res, out) {
+  var writeHead = res.writeHead
+    , stack = this.stack
+    , removed = ''
+    , index = 0;
+
+  function next(err) {
+    var layer, path, c;
+    req.url = removed + req.url;
+    req.originalUrl = req.originalUrl || req.url;
+    removed = '';
+
+    layer = stack[index++];
+
+    // all done
+    if (!layer || res.headerSent) {
+      // but wait! we have a parent
+      if (out) return out(err);
+
+      // error
+      if (err) {
+        var msg = 'production' == env
+          ? 'Internal Server Error'
+          : err.stack || err.toString();
+
+        // output to stderr in a non-test env
+        if ('test' != env) console.error(err.stack || err.toString());
+
+        // unable to respond
+        if (res.headerSent) return req.socket.destroy();
+
+        res.statusCode = 500;
+        res.setHeader('Content-Type', 'text/plain');
+        if ('HEAD' == req.method) return res.end();
+        res.end(msg);
+      } else {
+        res.statusCode = 404;
+        res.setHeader('Content-Type', 'text/plain');
+        if ('HEAD' == req.method) return res.end();
+        res.end('Cannot ' + req.method + ' ' + req.url);
+      }
+      return;
+    }
+
+    try {
+      path = parse(req.url).pathname;
+      if (undefined == path) path = '/';
+
+      // skip this layer if the route doesn't match.
+      if (0 != path.indexOf(layer.route)) return next(err);
+
+      c = path[layer.route.length];
+      if (c && '/' != c && '.' != c) return next(err);
+
+      // Call the layer handler
+      // Trim off the part of the url that matches the route
+      removed = layer.route;
+      req.url = req.url.substr(removed.length);
+
+      // Ensure leading slash
+      if ('/' != req.url[0]) req.url = '/' + req.url;
+
+      var arity = layer.handle.length;
+      if (err) {
+        if (arity === 4) {
+          layer.handle(err, req, res, next);
+        } else {
+          next(err);
+        }
+      } else if (arity < 4) {
+        layer.handle(req, res, next);
+      } else {
+        next();
+      }
+    } catch (e) {
+      if (e instanceof assert.AssertionError) {
+        console.error(e.stack + '\n');
+        next(e);
+      } else {
+        next(e);
+      }
+    }
+  }
+  next();
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/https.js b/weinre.server/node_modules/express/node_modules/connect/lib/https.js
new file mode 100644
index 0000000..9b09fa4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/https.js
@@ -0,0 +1,47 @@
+
+/*!
+ * Connect - HTTPServer
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var HTTPServer = require('./http').Server
+  , https = require('https');
+
+/**
+ * Initialize a new `Server` with the given
+ *`options` and `middleware`. The HTTPS api
+ * is identical to the [HTTP](http.html) server,
+ * however TLS `options` must be provided before
+ * passing in the optional middleware.
+ *
+ * @params {Object} options
+ * @params {Array} middleawre
+ * @return {Server}
+ * @api public
+ */
+
+var Server = exports.Server = function HTTPSServer(options, middleware) {
+  this.stack = [];
+  middleware.forEach(function(fn){
+    this.use(fn);
+  }, this);
+  https.Server.call(this, options, this.handle);
+};
+
+/**
+ * Inherit from `http.Server.prototype`.
+ */
+
+Server.prototype.__proto__ = https.Server.prototype;
+
+// mixin HTTPServer methods
+
+Object.keys(HTTPServer.prototype).forEach(function(method){
+  Server.prototype[method] = HTTPServer.prototype[method];
+});
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/index.js b/weinre.server/node_modules/express/node_modules/connect/lib/index.js
new file mode 100644
index 0000000..77b14c3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/index.js
@@ -0,0 +1,46 @@
+
+/**
+ * # Connect
+ *
+ * Connect is a middleware framework for node,
+ * shipping with over 11 bundled middleware and a rich choice of
+ * [3rd-party middleware](https://github.com/senchalabs/connect/wiki).
+ *
+ * Installation:
+ * 
+ *     $ npm install connect
+ * 
+ * API:
+ *
+ *  - [connect](connect.html) general
+ *  - [http](http.html) http server
+ *  - [https](https.html) https server
+ *
+ * Middleware:
+ *
+ *  - [logger](middleware-logger.html) request logger with custom format support
+ *  - [csrf](middleware-csrf.html) Cross-site request forgery protection
+ *  - [basicAuth](middleware-basicAuth.html) basic http authentication
+ *  - [bodyParser](middleware-bodyParser.html) extensible request body parser
+ *  - [cookieParser](middleware-cookieParser.html) cookie parser
+ *  - [session](middleware-session.html) session management support with bundled [MemoryStore](middleware-session-memory.html)
+ *  - [compiler](middleware-compiler.html) static asset compiler (sass, less, coffee-script, etc)
+ *  - [methodOverride](middleware-methodOverride.html) faux HTTP method support
+ *  - [responseTime](middleware-responseTime.html) calculates response-time and exposes via X-Response-Time
+ *  - [router](middleware-router.html) provides rich Sinatra / Express-like routing
+ *  - [staticCache](middleware-staticCache.html) memory cache layer for the static() middleware
+ *  - [static](middleware-static.html) streaming static file server supporting `Range` and more
+ *  - [directory](middleware-directory.html) directory listing middleware
+ *  - [vhost](middleware-vhost.html) virtual host sub-domain mapping middleware
+ *  - [favicon](middleware-favicon.html) efficient favicon server (with default icon)
+ *  - [limit](middleware-limit.html) limit the bytesize of request bodies
+ *  - [profiler](middleware-profiler.html) request profiler reporting response-time, memory usage, etc
+ *  - [query](middleware-query.html) automatic querystring parser, populating `req.query`
+ *  - [errorHandler](middleware-errorHandler.html) flexible error handler
+ *
+ * Internals:
+ *
+ *  - connect [utilities](utils.html)
+ *  - node monkey [patches](patch.html)
+ *
+ */
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js
new file mode 100644
index 0000000..3ff472b
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js
@@ -0,0 +1,93 @@
+
+/*!
+ * Connect - basicAuth
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , unauthorized = utils.unauthorized
+  , badRequest = utils.badRequest;
+
+/**
+ * Enfore basic authentication by providing a `callback(user, pass)`,
+ * which must return `true` in order to gain access. Alternatively an async
+ * method is provided as well, invoking `callback(user, pass, callback)`. Populates
+ * `req.remoteUser`. The final alternative is simply passing username / password
+ * strings.
+ *
+ * Examples:
+ *
+ *     connect(connect.basicAuth('username', 'password'));
+ *
+ *     connect(
+ *       connect.basicAuth(function(user, pass){
+ *         return 'tj' == user & 'wahoo' == pass;
+ *       })
+ *     );
+ *
+ *     connect(
+ *       connect.basicAuth(function(user, pass, fn){
+ *         User.authenticate({ user: user, pass: pass }, fn);
+ *       })
+ *     );
+ *
+ * @param {Function|String} callback or username
+ * @param {String} realm
+ * @api public
+ */
+
+module.exports = function basicAuth(callback, realm) {
+  var username, password;
+
+  // user / pass strings
+  if ('string' == typeof callback) {
+    username = callback;
+    password = realm;
+    if ('string' != typeof password) throw new Error('password argument required');
+    realm = arguments[2];
+    callback = function(user, pass){
+      return user == username && pass == password;
+    }
+  }
+
+  realm = realm || 'Authorization Required';
+
+  return function(req, res, next) {
+    var authorization = req.headers.authorization;
+
+    if (req.remoteUser) return next();
+    if (!authorization) return unauthorized(res, realm);
+
+    var parts = authorization.split(' ')
+      , scheme = parts[0]
+      , credentials = new Buffer(parts[1], 'base64').toString().split(':');
+
+    if ('Basic' != scheme) return badRequest(res);
+
+    // async
+    if (callback.length >= 3) {
+      var pause = utils.pause(req);
+      callback(credentials[0], credentials[1], function(err, user){
+        if (err || !user)  return unauthorized(res, realm);
+        req.remoteUser = user;
+        next();
+        pause.resume();
+      });
+    // sync
+    } else {
+      if (callback(credentials[0], credentials[1])) {
+        req.remoteUser = credentials[0];
+        next();
+      } else {
+        unauthorized(res, realm);
+      }
+    }
+  }
+};
+
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js
new file mode 100644
index 0000000..a52568c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js
@@ -0,0 +1,196 @@
+
+/*!
+ * Connect - bodyParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+  , formidable = require('formidable');
+
+/**
+ * Extract the mime type from the given request's
+ * _Content-Type_ header.
+ *
+ * @param  {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+function mime(req) {
+  var str = req.headers['content-type'] || '';
+  return str.split(';')[0];
+}
+
+/**
+ * Parse request bodies.
+ *
+ * By default _application/json_, _application/x-www-form-urlencoded_,
+ * and _multipart/form-data_ are supported, however you may map `connect.bodyParser.parse[contentType]`
+ * to a function receiving `(req, options, callback)`.
+ *
+ * Examples:
+ *
+ *      connect.createServer(
+ *          connect.bodyParser()
+ *        , function(req, res) {
+ *          res.end('viewing user ' + req.body.user.name);
+ *        }
+ *      );
+ *
+ *      $ curl -d 'user[name]=tj' http://localhost/
+ *      $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/
+ *
+ * Multipart req.files:
+ *
+ *   As a security measure files are stored in a separate object, stored
+ *   as `req.files`. This prevents attacks that may potentially alter
+ *   filenames, and depending on the application gain access to restricted files.
+ *
+ * Multipart configuration:
+ *
+ *  The `options` passed are provided to each parser function.
+ *  The _multipart/form-data_ parser merges these with formidable's
+ *  IncomingForm object, allowing you to tweak the upload directory,
+ *  size limits, etc. For example you may wish to retain the file extension
+ *  and change the upload directory:
+ *
+ *      server.use(bodyParser({ uploadDir: '/www/mysite.com/uploads' }));
+ *
+ *  View [node-formidable](https://github.com/felixge/node-formidable) for more information.
+ *
+ *  If you wish to use formidable directly within your app, and do not
+ *  desire this behaviour for multipart requests simply remove the
+ *  parser: 
+ *
+ *     delete connect.bodyParser.parse['multipart/form-data'];
+ *
+ *  Or
+ *
+ *     delete express.bodyParser.parse['multipart/form-data'];
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function bodyParser(options){
+  options = options || {};
+  return function bodyParser(req, res, next) {
+    if (req.body) return next();
+    req.body = {};
+
+    if ('GET' == req.method || 'HEAD' == req.method) return next();
+    var parser = exports.parse[mime(req)];
+    if (parser) {
+      parser(req, options, next);
+    } else {
+      next();
+    }
+  }
+};
+
+/**
+ * Parsers.
+ */
+
+exports.parse = {};
+
+/**
+ * Parse application/x-www-form-urlencoded.
+ */
+
+exports.parse['application/x-www-form-urlencoded'] = function(req, options, fn){
+  var buf = '';
+  req.setEncoding('utf8');
+  req.on('data', function(chunk){ buf += chunk });
+  req.on('end', function(){
+    try {
+      req.body = buf.length
+        ? qs.parse(buf)
+        : {};
+      fn();
+    } catch (err){
+      fn(err);
+    }
+  });
+};
+
+/**
+ * Parse application/json.
+ */
+
+exports.parse['application/json'] = function(req, options, fn){
+  var buf = '';
+  req.setEncoding('utf8');
+  req.on('data', function(chunk){ buf += chunk });
+  req.on('end', function(){
+    try {
+      req.body = buf.length
+        ? JSON.parse(buf)
+        : {};
+      fn();
+    } catch (err){
+      fn(err);
+    }
+  });
+};
+
+/**
+ * Parse multipart/form-data.
+ *
+ * TODO: make multiple support optional
+ * TODO: revisit "error" flag if it's a formidable bug
+ */
+
+exports.parse['multipart/form-data'] = function(req, options, fn){
+  var form = new formidable.IncomingForm
+    , data = {}
+    , files = {}
+    , done;
+
+  Object.keys(options).forEach(function(key){
+    form[key] = options[key];
+  });
+
+  function ondata(name, val, data){
+    if (Array.isArray(data[name])) {
+      data[name].push(val);
+    } else if (data[name]) {
+      data[name] = [data[name], val];
+    } else {
+      data[name] = val;
+    }
+  }
+
+  form.on('field', function(name, val){
+    ondata(name, val, data);
+  });
+
+  form.on('file', function(name, val){
+    ondata(name, val, files);
+  });
+
+  form.on('error', function(err){
+    fn(err);
+    done = true;
+  });
+
+  form.on('end', function(){
+    if (done) return;
+    try {
+      req.body = qs.parse(data);
+      req.files = qs.parse(files);
+      fn();
+    } catch (err) {
+      fn(err);
+    }
+  });
+
+  form.parse(req);
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/compiler.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/compiler.js
new file mode 100644
index 0000000..dc4dd66
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/compiler.js
@@ -0,0 +1,163 @@
+
+/*!
+ * Connect - compiler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , path = require('path')
+  , parse = require('url').parse;
+
+/**
+ * Require cache.
+ */
+
+var cache = {};
+
+/**
+ * Setup compiler.
+ *
+ * Options:
+ *
+ *   - `src`     Source directory, defaults to **CWD**.
+ *   - `dest`    Destination directory, defaults `src`.
+ *   - `enable`  Array of enabled compilers.
+ *
+ * Compilers:
+ *
+ *   - `sass`   Compiles sass to css
+ *   - `less`   Compiles less to css
+ *   - `coffeescript`   Compiles coffee to js
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+exports = module.exports = function compiler(options){
+  options = options || {};
+
+  var srcDir = options.src || process.cwd()
+    , destDir = options.dest || srcDir
+    , enable = options.enable;
+
+  if (!enable || enable.length === 0) {
+    throw new Error('compiler\'s "enable" option is not set, nothing will be compiled.');
+  }
+
+  return function compiler(req, res, next){
+    if ('GET' != req.method) return next();
+    var pathname = parse(req.url).pathname;
+    for (var i = 0, len = enable.length; i < len; ++i) {
+      var name = enable[i]
+        , compiler = compilers[name];
+      if (compiler.match.test(pathname)) {
+        var src = (srcDir + pathname).replace(compiler.match, compiler.ext)
+          , dest = destDir + pathname;
+
+        // Compare mtimes
+        fs.stat(src, function(err, srcStats){
+          if (err) {
+            if ('ENOENT' == err.code) {
+              next();
+            } else {
+              next(err);
+            }
+          } else {
+            fs.stat(dest, function(err, destStats){
+              if (err) {
+                // Oh snap! it does not exist, compile it
+                if ('ENOENT' == err.code) {
+                  compile();
+                } else {
+                  next(err);
+                }
+              } else {
+                // Source has changed, compile it
+                if (srcStats.mtime > destStats.mtime) {
+                  compile();
+                } else {
+                  // Defer file serving
+                  next();
+                }
+              }
+            });
+          }
+        });
+
+        // Compile to the destination
+        function compile() {
+          fs.readFile(src, 'utf8', function(err, str){
+            if (err) {
+              next(err);
+            } else {
+              compiler.compile(str, function(err, str){
+                if (err) {
+                  next(err);
+                } else {
+                  fs.writeFile(dest, str, 'utf8', function(err){
+                    next(err);
+                  });
+                }
+              });
+            }
+          });
+        }
+        return;
+      }
+    }
+    next();
+  };
+};
+
+/**
+ * Bundled compilers:
+ *
+ *  - [sass](http://github.com/visionmedia/sass.js) to _css_
+ *  - [less](http://github.com/cloudhead/less.js) to _css_
+ *  - [coffee](http://github.com/jashkenas/coffee-script) to _js_
+ */
+
+var compilers = exports.compilers = {
+  sass: {
+    match: /\.css$/,
+    ext: '.sass',
+    compile: function(str, fn){
+      var sass = cache.sass || (cache.sass = require('sass'));
+      try {
+        fn(null, sass.render(str));
+      } catch (err) {
+        fn(err);
+      }
+    }
+  },
+  less: {
+    match: /\.css$/,
+    ext: '.less',
+    compile: function(str, fn){
+      var less = cache.less || (cache.less = require('less'));
+      try {
+        less.render(str, fn);
+      } catch (err) {
+        fn(err);
+      }
+    }
+  },
+  coffeescript: {
+    match: /\.js$/,
+    ext: '.coffee',
+    compile: function(str, fn){
+      var coffee = cache.coffee || (cache.coffee = require('coffee-script'));
+      try {
+        fn(null, coffee.compile(str));
+      } catch (err) {
+        fn(err);
+      }
+    }
+  }
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js
new file mode 100644
index 0000000..d6b69de
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js
@@ -0,0 +1,46 @@
+
+/*!
+ * Connect - cookieParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./../utils');
+
+/**
+ * Parse _Cookie_ header and populate `req.cookies`
+ * with an object keyed by the cookie names.
+ *
+ * Examples:
+ *
+ *     connect.createServer(
+ *         connect.cookieParser()
+ *       , function(req, res, next){
+ *         res.end(JSON.stringify(req.cookies));
+ *       }
+ *     );
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function cookieParser(){
+  return function cookieParser(req, res, next) {
+    var cookie = req.headers.cookie;
+    if (req.cookies) return next();
+    req.cookies = {};
+    if (cookie) {
+      try {
+        req.cookies = utils.parseCookie(cookie);
+      } catch (err) {
+        return next(err);
+      }
+    }
+    next();
+  };
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/csrf.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/csrf.js
new file mode 100644
index 0000000..1dcf0d1
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/csrf.js
@@ -0,0 +1,105 @@
+
+/*!
+ * Connect - csrf
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , crypto = require('crypto');
+
+/**
+ * CRSF protection middleware.
+ *
+ * By default this middleware generates a token named "_csrf"
+ * which should be added to requests which mutate
+ * state, within a hidden form field, query-string etc. This
+ * token is validated against the visitor's `req.session._csrf`
+ * property which is re-generated per request.
+ *
+ * The default `value` function checks `req.body` generated
+ * by the `bodyParser()` middleware, `req.query` generated
+ * by `query()`, and the "X-CSRF-Token" header field.
+ *
+ * This middleware requires session support, thus should be added
+ * somewhere _below_ `session()` and `cookieParser()`.
+ *
+ * Examples:
+ *
+ *      var form = '\n\
+ *        <form action="/" method="post">\n\
+ *          <input type="hidden" name="_csrf" value="{token}" />\n\
+ *          <input type="text" name="user[name]" value="{user}" />\n\
+ *          <input type="password" name="user[pass]" />\n\
+ *          <input type="submit" value="Login" />\n\
+ *        </form>\n\
+ *      '; 
+ *      
+ *      connect(
+ *          connect.cookieParser()
+ *        , connect.session({ secret: 'keyboard cat' })
+ *        , connect.bodyParser()
+ *        , connect.csrf()
+ *      
+ *        , function(req, res, next){
+ *          if ('POST' != req.method) return next();
+ *          req.session.user = req.body.user;
+ *          next();
+ *        }
+ *      
+ *        , function(req, res){
+ *          res.setHeader('Content-Type', 'text/html');
+ *          var body = form
+ *            .replace('{token}', req.session._csrf)
+ *            .replace('{user}', req.session.user && req.session.user.name || '');
+ *          res.end(body);
+ *        }
+ *      ).listen(3000);
+ *
+ * Options:
+ *
+ *    - `value` a function accepting the request, returning the token 
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+module.exports = function csrf(options) {
+  var options = options || {}
+    , value = options.value || defaultValue;
+
+  return function(req, res, next){
+    // generate CSRF token
+    var token = req.session._csrf || (req.session._csrf = utils.uid(24));
+
+    // ignore GET (for now)
+    if ('GET' == req.method) return next();
+
+    // determine value
+    var val = value(req);
+
+    // check
+    if (val != token) return utils.forbidden(res);
+    
+    next();
+  }
+};
+
+/**
+ * Default value function, checking the `req.body`
+ * and `req.query` for the CSRF token.
+ *
+ * @param {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+function defaultValue(req) {
+  return (req.body && req.body._csrf)
+    || (req.query && req.query._csrf)
+    || (req.headers['x-csrf-token']);
+}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/directory.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/directory.js
new file mode 100644
index 0000000..df5b5e6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/directory.js
@@ -0,0 +1,222 @@
+
+/*!
+ * Connect - directory
+ * Copyright(c) 2011 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+// TODO: icon / style for directories
+// TODO: arrow key navigation
+// TODO: make icons extensible
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , parse = require('url').parse
+  , utils = require('../utils')
+  , path = require('path')
+  , normalize = path.normalize
+  , extname = path.extname
+  , join = path.join;
+
+/**
+ * Icon cache.
+ */
+
+var cache = {};
+
+/**
+ * Serve directory listings with the given `root` path.
+ *
+ * Options:
+ *
+ *  - `hidden` display hidden (dot) files. Defaults to false.
+ *  - `icons`  display icons. Defaults to false.
+ *  - `filter` Apply this filter function to files. Defaults to false.
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function directory(root, options){
+  options = options || {};
+
+  // root required
+  if (!root) throw new Error('directory() root path required');
+  var hidden = options.hidden
+    , icons = options.icons
+    , filter = options.filter
+    , root = normalize(root);
+
+  return function directory(req, res, next) {
+    var accept = req.headers.accept || 'text/plain'
+      , url = parse(req.url)
+      , dir = decodeURIComponent(url.pathname)
+      , path = normalize(join(root, dir))
+      , originalUrl = parse(req.originalUrl)
+      , originalDir = decodeURIComponent(originalUrl.pathname)
+      , showUp = path != root && path != root + '/';
+
+    // null byte(s)
+    if (~path.indexOf('\0')) return utils.badRequest(res);
+
+    // malicious path
+    if (0 != path.indexOf(root)) return utils.forbidden(res);
+
+    // check if we have a directory
+    fs.stat(path, function(err, stat){
+      if (err) return 'ENOENT' == err.code
+        ? next()
+        : next(err);
+
+      if (!stat.isDirectory()) return next();
+
+      // fetch files
+      fs.readdir(path, function(err, files){
+        if (err) return next(err);
+        if (!hidden) files = removeHidden(files);
+        if (filter) files = files.filter(filter);
+        files.sort();
+        // content-negotiation
+        for (var key in exports) {
+          if (~accept.indexOf(key) || ~accept.indexOf('*/*')) {
+            exports[key](req, res, files, next, originalDir, showUp, icons);
+            return;
+          }
+        }
+        utils.notAcceptable(res);
+      });
+    });
+  };
+};
+
+/**
+ * Respond with text/html.
+ */
+
+exports.html = function(req, res, files, next, dir, showUp, icons){
+  fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){
+    if (err) return next(err);
+    fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){
+      if (err) return next(err);
+      if (showUp) files.unshift('..');
+      str = str
+        .replace('{style}', style)
+        .replace('{files}', html(files, dir, icons))
+        .replace('{directory}', dir)
+		.replace('{linked-path}', htmlPath(dir));
+      res.setHeader('Content-Type', 'text/html');
+      res.setHeader('Content-Length', str.length);
+      res.end(str);
+    });
+  });
+};
+
+/**
+ * Respond with application/json.
+ */
+
+exports.json = function(req, res, files){
+  files = JSON.stringify(files);
+  res.setHeader('Content-Type', 'application/json');
+  res.setHeader('Content-Length', files.length);
+  res.end(files);
+};
+
+/**
+ * Respond with text/plain.
+ */
+
+exports.plain = function(req, res, files){
+  files = files.join('\n') + '\n';
+  res.setHeader('Content-Type', 'text/plain');
+  res.setHeader('Content-Length', files.length);
+  res.end(files);
+};
+
+/**
+ * Map html `dir`, returning a linked path.
+ */
+
+function htmlPath(dir) {
+  var curr = [];
+  return dir.split('/').map(function(part){
+    curr.push(part);
+    return '<a href="' + curr.join('/') + '">' + part + '</a>';
+  }).join(' / ');
+}
+
+/**
+ * Map html `files`, returning an html unordered list.
+ */
+
+function html(files, dir, useIcons) {
+  return '<ul id="files">' + files.map(function(file){
+    var icon = ''
+      , classes = [];
+
+    if (useIcons && '..' != file) {
+      icon = icons[extname(file)] || icons.default;
+      icon = '<img src="data:image/png;base64,' + load(icon) + '" />';
+      classes.push('icon');
+    }
+
+    return '<li><a href="'
+      + join(dir, file)
+      + '" class="'
+      + classes.join(' ') + '"'
+      + ' title="' + file + '">'
+      + icon + file + '</a></li>';
+
+  }).join('\n') + '</ul>';
+}
+
+/**
+ * Load and cache the given `icon`.
+ *
+ * @param {String} icon
+ * @return {String}
+ * @api private
+ */
+
+function load(icon) {
+  if (cache[icon]) return cache[icon];
+  return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');
+}
+
+/**
+ * Filter "hidden" `files`, aka files
+ * beginning with a `.`.
+ *
+ * @param {Array} files
+ * @return {Array}
+ * @api private
+ */
+
+function removeHidden(files) {
+  return files.filter(function(file){
+    return '.' != file[0];
+  });
+}
+
+/**
+ * Icon map.
+ */
+
+var icons = {
+    '.js': 'page_white_code_red.png'
+  , '.c': 'page_white_c.png'
+  , '.h': 'page_white_h.png'
+  , '.cc': 'page_white_cplusplus.png'
+  , '.php': 'page_white_php.png'
+  , '.rb': 'page_white_ruby.png'
+  , '.cpp': 'page_white_cplusplus.png'
+  , '.swf': 'page_white_flash.png'
+  , '.pdf': 'page_white_acrobat.png'
+  , 'default': 'page_white.png'
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
new file mode 100644
index 0000000..f2fc44f
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
@@ -0,0 +1,100 @@
+/*!
+ * Connect - errorHandler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , url = require('url')
+  , fs = require('fs');
+
+/**
+ * Flexible error handler, providing (_optional_) stack traces
+ * and error message responses for requests accepting text, html,
+ * or json.
+ *
+ * Options:
+ *
+ *   - `showStack`, `stack` respond with both the error message and stack trace. Defaults to `false`
+ *   - `showMessage`, `message`, respond with the exception message only. Defaults to `false`
+ *   - `dumpExceptions`, `dump`, dump exceptions to stderr (without terminating the process). Defaults to `false`
+ *
+ * Text:
+ *
+ *   By default, and when _text/plain_ is accepted a simple stack trace
+ *   or error message will be returned.
+ *
+ * JSON:
+ *
+ *   When _application/json_ is accepted, connect will respond with
+ *   an object in the form of `{ "error": error }`. 
+ *
+ * HTML:
+ *
+ *   When accepted connect will output a nice html stack trace.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function errorHandler(options){
+  options = options || {};
+
+  // defaults
+  var showStack = options.showStack || options.stack
+    , showMessage = options.showMessage || options.message
+    , dumpExceptions = options.dumpExceptions || options.dump
+    , formatUrl = options.formatUrl;
+
+  return function errorHandler(err, req, res, next){
+    res.statusCode = 500;
+    if (dumpExceptions) console.error(err.stack);
+    if (showStack) {
+      var accept = req.headers.accept || '';
+      // html
+      if (~accept.indexOf('html')) {
+        fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){
+          fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){
+            var stack = (err.stack || '')
+              .split('\n').slice(1)
+              .map(function(v){ return '<li>' + v + '</li>'; }).join('');
+              html = html
+                .replace('{style}', style)
+                .replace('{stack}', stack)
+                .replace('{title}', exports.title)
+                .replace(/\{error\}/g, utils.escape(err.toString()));
+              res.setHeader('Content-Type', 'text/html');
+              res.end(html);
+          });
+        });
+      // json
+      } else if (~accept.indexOf('json')) {
+        var json = JSON.stringify({ error: err });
+        res.setHeader('Content-Type', 'application/json');
+        res.end(json);
+      // plain text
+      } else {
+        res.writeHead(500, { 'Content-Type': 'text/plain' });
+        res.end(err.stack);
+      }
+    } else {
+      var body = showMessage
+        ? err.toString()
+        : 'Internal Server Error';
+      res.setHeader('Content-Type', 'text/plain');
+      res.end(body);
+    }
+  };
+};
+
+/**
+ * Template title.
+ */
+
+exports.title = 'Connect';
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/favicon.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/favicon.js
new file mode 100644
index 0000000..8eeafba
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/favicon.js
@@ -0,0 +1,76 @@
+
+/*!
+ * Connect - favicon
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , utils = require('../utils');
+
+/**
+ * Favicon cache.
+ */
+
+var icon;
+
+/**
+ * By default serves the connect favicon, or the favicon
+ * located by the given `path`.
+ *
+ * Options:
+ *
+ *   - `maxAge`  cache-control max-age directive, defaulting to 1 day
+ *
+ * Examples:
+ *
+ *     connect.createServer(
+ *       connect.favicon()    
+ *     );
+ *
+ *     connect.createServer(
+ *       connect.favicon(__dirname + '/public/favicon.ico')    
+ *     );
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function favicon(path, options){
+  var options = options || {}
+    , path = path || __dirname + '/../public/favicon.ico'
+    , maxAge = options.maxAge || 86400000;
+
+  return function favicon(req, res, next){
+    if ('/favicon.ico' == req.url) {
+      if (icon) {
+        res.writeHead(200, icon.headers);
+        res.end(icon.body);
+      } else {
+        fs.readFile(path, function(err, buf){
+          if (err) return next(err);
+          icon = {
+            headers: {
+                'Content-Type': 'image/x-icon'
+              , 'Content-Length': buf.length
+              , 'ETag': '"' + utils.md5(buf) + '"'
+              , 'Cache-Control': 'public, max-age=' + (maxAge / 1000)
+            },
+            body: buf
+          };
+          res.writeHead(200, icon.headers);
+          res.end(icon.body);
+        });
+      }
+    } else {
+      next();
+    }
+  };
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/limit.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/limit.js
new file mode 100644
index 0000000..4dafdd3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/limit.js
@@ -0,0 +1,82 @@
+
+/*!
+ * Connect - limit
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Limit request bodies to the given size in `bytes`.
+ *
+ * A string representation of the bytesize may also be passed,
+ * for example "5mb", "200kb", "1gb", etc.
+ *
+ * Examples:
+ *
+ *     var server = connect(
+ *       connect.limit('5.5mb')
+ *     ).listen(3000);
+ *
+ * TODO: pause EV_READ
+ *
+ * @param {Number|String} bytes
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function limit(bytes){
+  if ('string' == typeof bytes) bytes = parse(bytes);
+  if ('number' != typeof bytes) throw new Error('limit() bytes required');
+  return function limit(req, res, next){
+    var received = 0
+      , len = req.headers['content-length']
+        ? parseInt(req.headers['content-length'], 10)
+        : null;
+
+    // deny the request
+    function deny() {
+      req.destroy();
+    }
+
+    // self-awareness
+    if (req._limit) return next();
+    req._limit = true;
+
+    // limit by content-length
+    if (len && len > bytes) {
+      res.statusCode = 413;
+      res.end('Request Entity Too Large');
+      return;
+    }
+
+    // limit
+    req.on('data', function(chunk){
+      received += chunk.length;
+      if (received > bytes) deny();
+    });
+
+    next();
+  };
+};
+
+/**
+ * Parse byte `size` string.
+ *
+ * @param {String} size
+ * @return {Number}
+ * @api private
+ */
+
+function parse(size) {
+  var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/)
+    , n = parseFloat(parts[1])
+    , type = parts[2];
+
+  var map = {
+      kb: 1024
+    , mb: 1024 * 1024
+    , gb: 1024 * 1024 * 1024
+  };
+
+  return map[type] * n;
+}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/logger.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/logger.js
new file mode 100644
index 0000000..75cc5aa
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/logger.js
@@ -0,0 +1,299 @@
+
+/*!
+ * Connect - logger
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Log buffer.
+ */
+
+var buf = [];
+
+/**
+ * Default log buffer duration.
+ */
+
+var defaultBufferDuration = 1000;
+
+/**
+ * Log requests with the given `options` or a `format` string.
+ *
+ * Options:
+ *
+ *   - `format`  Format string, see below for tokens
+ *   - `stream`  Output stream, defaults to _stdout_
+ *   - `buffer`  Buffer duration, defaults to 1000ms when _true_
+ *   - `immediate`  Write log line on request instead of response (for response times)
+ *
+ * Tokens:
+ *
+ *   - `:req[header]` ex: `:req[Accept]`
+ *   - `:res[header]` ex: `:res[Content-Length]`
+ *   - `:http-version`
+ *   - `:response-time`
+ *   - `:remote-addr`
+ *   - `:date`
+ *   - `:method`
+ *   - `:url`
+ *   - `:referrer`
+ *   - `:user-agent`
+ *   - `:status`
+ *
+ * Formats:
+ *
+ *   Pre-defined formats that ship with connect:
+ *
+ *    - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'
+ *    - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'
+ *    - `tiny`  ':method :url :status :res[content-length] - :response-time ms'
+ *    - `dev` concise output colored by response status for development use
+ *
+ * Examples:
+ *
+ *      connect.logger() // default
+ *      connect.logger('short')
+ *      connect.logger('tiny')
+ *      connect.logger('dev')
+ *      connect.logger(':method :url - :referrer')
+ *      connect.logger(':req[content-type] -> :res[content-type]')
+ *      connect.logger(function(req, res){ return 'some format string' })
+ *
+ * Defining Tokens:
+ *
+ *   To define a token, simply invoke `connect.logger.token()` with the
+ *   name and a callback function. The value returned is then available
+ *   as ":type" in this case.
+ *
+ *      connect.logger.token('type', function(req, res){ return req.headers['content-type']; })
+ *
+ * Defining Formats:
+ *
+ *   All default formats are defined this way, however it's public API as well:
+ *
+ *       connect.logger.format('name', 'string or function')
+ *
+ * @param {String|Function|Object} format or options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function logger(options) {
+  if ('object' == typeof options) {
+    options = options || {};
+  } else if (options) {
+    options = { format: options };
+  } else {
+    options = {};
+  }
+
+  // output on request instead of response
+  var immediate = options.immediate;
+
+  // format name
+  var fmt = exports[options.format] || options.format || exports.default;
+
+  // compile format
+  if ('function' != typeof fmt) fmt = compile(fmt);
+
+  // options
+  var stream = options.stream || process.stdout
+    , buffer = options.buffer;
+
+  // buffering support
+  if (buffer) {
+    var realStream = stream
+      , interval = 'number' == typeof buffer
+        ? buffer
+        : defaultBufferDuration;
+
+    // flush interval
+    setInterval(function(){
+      if (buf.length) {
+        realStream.write(buf.join(''), 'ascii');
+        buf.length = 0;
+      }
+    }, interval); 
+
+    // swap the stream
+    stream = {
+      write: function(str){
+        buf.push(str);
+      }
+    };
+  }
+
+  return function logger(req, res, next) {
+    req._startTime = new Date;
+
+    // mount safety
+    if (req._logging) return next();
+
+    // flag as logging
+    req._logging = true;
+
+    // immediate
+    if (immediate) {
+      var line = fmt(exports, req, res);
+      if (null == line) return;
+      stream.write(line + '\n', 'ascii');
+    } else {
+      // proxy end to output loggging
+      var end = res.end;
+      res.end = function(chunk, encoding){
+        res.end = end;
+        res.end(chunk, encoding);
+        var line = fmt(exports, req, res);
+        if (null == line) return;
+        stream.write(line + '\n', 'ascii');
+      };
+    }
+
+
+    next();
+  };
+};
+
+/**
+ * Compile `fmt` into a function.
+ *
+ * @param {String} fmt
+ * @return {Function}
+ * @api private
+ */
+
+function compile(fmt) {
+  fmt = fmt.replace(/"/g, '\\"');
+  var js = '  return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){
+    return '"\n    + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "';
+  }) + '";'
+  return new Function('tokens, req, res', js);
+};
+
+/**
+ * Define a token function with the given `name`,
+ * and callback `fn(req, res)`.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.token = function(name, fn) {
+  exports[name] = fn;
+  return this;
+};
+
+/**
+ * Define a `fmt` with the given `name`.
+ *
+ * @param {String} name
+ * @param {String|Function} fmt
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.format = function(name, str){
+  exports[name] = str;
+  return this;
+};
+
+// default format
+
+exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"');
+
+// short format
+
+exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms');
+
+// tiny format
+
+exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms');
+
+// dev (colored)
+
+exports.format('dev', function(tokens, req, res){
+  var status = res.statusCode
+    , color = 32;
+
+  if (status >= 500) color = 31
+  else if (status >= 400) color = 33
+  else if (status >= 300) color = 36;
+
+  return '\033[90m' + req.method
+    + ' ' + req.originalUrl + ' '
+    + '\033[' + color + 'm' + res.statusCode
+    + ' \033[90m'
+    + (new Date - req._startTime)
+    + 'ms\033[0m';
+});
+
+// request url
+
+exports.token('url', function(req){
+  return req.originalUrl;
+});
+
+// request method
+
+exports.token('method', function(req){
+  return req.method;
+});
+
+// response time in milliseconds
+
+exports.token('response-time', function(req){
+  return new Date - req._startTime;
+});
+
+// UTC date
+
+exports.token('date', function(){
+  return new Date().toUTCString();
+});
+
+// response status code
+
+exports.token('status', function(req, res){
+  return res.statusCode;
+});
+
+// normalized referrer
+
+exports.token('referrer', function(req){
+  return req.headers['referer'] || req.headers['referrer'];
+});
+
+// remote address
+
+exports.token('remote-addr', function(req){
+  return req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress));
+});
+
+// HTTP version
+
+exports.token('http-version', function(req){
+  return req.httpVersionMajor + '.' + req.httpVersionMinor;
+});
+
+// UA string
+
+exports.token('user-agent', function(req){
+  return req.headers['user-agent'];
+});
+
+// request header
+
+exports.token('req', function(req, res, field){
+  return req.headers[field.toLowerCase()];
+});
+
+// response header
+
+exports.token('res', function(req, res, field){
+  return (res._headers || {})[field.toLowerCase()];
+});
+
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js
new file mode 100644
index 0000000..db4e9f3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js
@@ -0,0 +1,38 @@
+
+/*!
+ * Connect - methodOverride
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Provides faux HTTP method support.
+ * 
+ * Pass an optional `key` to use when checking for
+ * a method override, othewise defaults to _\_method_.
+ * The original method is available via `req.originalMethod`.
+ *
+ * @param {String} key
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function methodOverride(key){
+  key = key || "_method";
+  return function methodOverride(req, res, next) {
+    req.originalMethod = req.originalMethod || req.method;
+
+    // req.body
+    if (req.body && key in req.body) {
+      req.method = req.body[key].toUpperCase();
+      delete req.body[key];
+    // check X-HTTP-Method-Override
+    } else if (req.headers['x-http-method-override']) {
+      req.method = req.headers['x-http-method-override'].toUpperCase();
+    }
+    
+    next();
+  };
+};
+
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/profiler.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/profiler.js
new file mode 100644
index 0000000..b0b5bac
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/profiler.js
@@ -0,0 +1,100 @@
+
+/*!
+ * Connect - profiler
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Profile the duration of a request.
+ *
+ * Typically this middleware should be utilized
+ * _above_ all others, as it proxies the `res.end()`
+ * method, being first allows it to encapsulate all
+ * other middleware.
+ *
+ * Example Output:
+ *
+ *      GET /
+ *      response time 2ms
+ *      memory rss 52.00kb
+ *      memory vsize 2.07mb
+ *      heap before 3.76mb / 8.15mb
+ *      heap after 3.80mb / 8.15mb
+ *
+ * @api public
+ */
+
+module.exports = function profiler(){
+  return function(req, res, next){
+    var end = res.end
+      , start = snapshot();
+
+    // state snapshot
+    function snapshot() {
+      return {
+          mem: process.memoryUsage()
+        , time: new Date
+      };
+    }
+
+    // proxy res.end()
+    res.end = function(data, encoding){
+      res.end = end;
+      res.end(data, encoding);
+      compare(req, start, snapshot())
+    };
+
+    next();
+  }
+};
+
+/**
+ * Compare `start` / `end` snapshots.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} start
+ * @param {Object} end
+ * @api private
+ */
+
+function compare(req, start, end) {
+  console.log();
+  row(req.method, req.url);
+  row('response time:', (end.time - start.time) + 'ms');
+  row('memory rss:', formatBytes(end.mem.rss - start.mem.rss));
+  row('memory vsize:', formatBytes(end.mem.vsize - start.mem.vsize));
+  row('heap before:', formatBytes(start.mem.heapUsed) + ' / ' + formatBytes(start.mem.heapTotal));
+  row('heap after:', formatBytes(end.mem.heapUsed) + ' / ' + formatBytes(end.mem.heapTotal));
+  console.log();
+}
+
+/**
+ * Row helper
+ *
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function row(key, val) {
+  console.log('  \033[90m%s\033[0m \033[36m%s\033[0m', key, val);
+}
+
+/**
+ * Format byte-size.
+ *
+ * @param {Number} bytes
+ * @return {String}
+ * @api private
+ */
+
+function formatBytes(bytes) {
+  var kb = 1024
+    , mb = 1024 * kb
+    , gb = 1024 * mb;
+  if (bytes < kb) return bytes + 'b';
+  if (bytes < mb) return (bytes / kb).toFixed(2) + 'kb';
+  if (bytes < gb) return (bytes / mb).toFixed(2) + 'mb';
+  return (bytes / gb).toFixed(2) + 'gb';
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/query.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/query.js
new file mode 100644
index 0000000..d3b1acd
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/query.js
@@ -0,0 +1,40 @@
+
+/*!
+ * Connect - query
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+  , parse = require('url').parse;
+
+/**
+ * Automatically parse the query-string when available,
+ * populating the `req.query` object.
+ *
+ * Examples:
+ *
+ *     connect(
+ *         connect.query()
+ *       , function(req, res){
+ *         res.end(JSON.stringify(req.query));
+ *       }
+ *     ).listen(3000);
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function query(){
+  return function query(req, res, next){
+    req.query = ~req.url.indexOf('?')
+      ? qs.parse(parse(req.url).query)
+      : {};
+    next();
+  };
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/responseTime.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
new file mode 100644
index 0000000..2b2133a
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
@@ -0,0 +1,34 @@
+
+/*!
+ * Connect - responseTime
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Adds the `X-Response-Time` header displaying the response
+ * duration in milliseconds.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function responseTime(){
+  return function(req, res, next){
+    var writeHead = res.writeHead
+      , start = new Date;
+
+    if (res._responseTime) return next();
+    res._responseTime = true;
+
+    // proxy writeHead to calculate duration
+    res.writeHead = function(status, headers){
+      var duration = new Date - start;
+      res.setHeader('X-Response-Time', duration + 'ms');
+      res.writeHead = writeHead;
+      res.writeHead(status, headers);
+    };
+
+    next();
+  };
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/router.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/router.js
new file mode 100644
index 0000000..a07452e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/router.js
@@ -0,0 +1,379 @@
+
+/*!
+ * Connect - router
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , parse = require('url').parse;
+
+/**
+ * Expose router.
+ */
+
+exports = module.exports = router;
+
+/**
+ * Supported HTTP / WebDAV methods.
+ */
+
+var _methods = exports.methods = [
+    'get'
+  , 'post'
+  , 'put'
+  , 'delete'
+  , 'connect'
+  , 'options'
+  , 'trace'
+  , 'copy'
+  , 'lock'
+  , 'mkcol'
+  , 'move'
+  , 'propfind'
+  , 'proppatch'
+  , 'unlock'
+  , 'report'
+  , 'mkactivity'
+  , 'checkout'
+  , 'merge'
+];
+
+/**
+ * Provides Sinatra and Express-like routing capabilities.
+ *
+ * Examples:
+ *
+ *     connect.router(function(app){
+ *       app.get('/user/:id', function(req, res, next){
+ *         // populates req.params.id
+ *       });
+ *       app.put('/user/:id', function(req, res, next){
+ *         // populates req.params.id
+ *       });
+ *     })
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @api public
+ */
+
+function router(fn){
+  var self = this
+    , methods = {}
+    , routes = {}
+    , params = {};
+
+  if (!fn) throw new Error('router provider requires a callback function');
+
+  // Generate method functions
+  _methods.forEach(function(method){
+    methods[method] = generateMethodFunction(method.toUpperCase());
+  });
+
+  // Alias del -> delete
+  methods.del = methods.delete;
+
+  // Apply callback to all methods
+  methods.all = function(){
+    var args = arguments;
+    _methods.forEach(function(name){
+      methods[name].apply(this, args);
+    });
+    return self;
+  };
+
+  // Register param callback
+  methods.param = function(name, fn){
+    params[name] = fn;
+  };
+      
+  fn.call(this, methods);
+
+  function generateMethodFunction(name) {
+    var localRoutes = routes[name] = routes[name] || [];
+    return function(path, fn){
+      var keys = []
+        , middleware = [];
+
+      // slice middleware
+      if (arguments.length > 2) {
+        middleware = Array.prototype.slice.call(arguments, 1, arguments.length);
+        fn = middleware.pop();
+        middleware = utils.flatten(middleware);
+      }
+
+      fn.middleware = middleware;
+
+      if (!path) throw new Error(name + ' route requires a path');
+      if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
+      var regexp = path instanceof RegExp
+        ? path
+        : normalizePath(path, keys);
+      localRoutes.push({
+          fn: fn
+        , path: regexp
+        , keys: keys
+        , orig: path
+        , method: name
+      });
+      return self;
+    };
+  }
+
+  function router(req, res, next){
+    var route
+      , self = this;
+
+    (function pass(i){
+      if (route = match(req, routes, i)) {
+        var i = 0
+          , keys = route.keys;
+
+        req.params = route.params;
+
+        // Param preconditions
+        (function param(err) {
+          try {
+            var key = keys[i++]
+              , val = req.params[key]
+              , fn = params[key];
+
+            if ('route' == err) {
+              pass(req._route_index + 1);
+            // Error
+            } else if (err) {
+              next(err);
+            // Param has callback
+            } else if (fn) {
+              // Return style
+              if (1 == fn.length) {
+                req.params[key] = fn(val);
+                param();
+              // Middleware style
+              } else {
+                fn(req, res, param, val);
+              }
+            // Finished processing params
+            } else if (!key) {
+              // route middleware
+              i = 0;
+              (function nextMiddleware(err){
+                var fn = route.middleware[i++];
+                if ('route' == err) {
+                  pass(req._route_index + 1);
+                } else if (err) {
+                  next(err);
+                } else if (fn) {
+                  fn(req, res, nextMiddleware);
+                } else {
+                  route.call(self, req, res, function(err){
+                    if (err) {
+                      next(err);
+                    } else {
+                      pass(req._route_index + 1);
+                    }
+                  });
+                }
+              })();
+            // More params
+            } else {
+              param();
+            }
+          } catch (err) {
+            next(err);
+          }
+        })();
+      } else if ('OPTIONS' == req.method) {
+        options(req, res, routes);
+      } else {
+        next();
+      }
+    })();
+  };
+
+  router.remove = function(path, method){
+    var fns = router.lookup(path, method);
+    fns.forEach(function(fn){
+      routes[fn.method].splice(fn.index, 1);
+    });
+  };
+
+  router.lookup = function(path, method, ret){
+    ret = ret || [];
+
+    // method specific lookup
+    if (method) {
+      method = method.toUpperCase();
+      if (routes[method]) {
+        routes[method].forEach(function(route, i){
+          if (path == route.orig) {
+            var fn = route.fn;
+            fn.regexp = route.path;
+            fn.keys = route.keys;
+            fn.path = route.orig;
+            fn.method = route.method;
+            fn.index = i;
+            ret.push(fn);
+          }
+        });
+      }
+    // global lookup
+    } else {
+      _methods.forEach(function(method){
+        router.lookup(path, method, ret);
+      });
+    }
+
+    return ret;
+  };
+
+  router.match = function(url, method, ret){
+    var ret = ret || []
+      , i = 0
+      , fn
+      , req;
+
+    // method specific matches
+    if (method) {
+      method = method.toUpperCase();
+      req = { url: url, method: method };
+      while (fn = match(req, routes, i)) {
+        i = req._route_index + 1;
+        ret.push(fn);
+      } 
+    // global matches
+    } else {
+      _methods.forEach(function(method){
+        router.match(url, method, ret);
+      });
+    }
+
+    return ret;
+  };
+
+  return router;
+}
+
+/**
+ * Respond to OPTIONS.
+ *
+ * @param {ServerRequest} req
+ * @param {ServerResponse} req
+ * @param {Array} routes
+ * @api private
+ */
+
+function options(req, res, routes) {
+  var pathname = parse(req.url).pathname
+    , body = optionsFor(pathname, routes).join(',');
+  res.writeHead(200, {
+      'Content-Length': body.length
+    , 'Allow': body
+  });
+  res.end(body);
+}
+
+/**
+ * Return OPTIONS array for the given `path`, matching `routes`.
+ *
+ * @param {String} path
+ * @param {Array} routes
+ * @return {Array}
+ * @api private
+ */
+
+function optionsFor(path, routes) {
+  return _methods.filter(function(method){
+    var arr = routes[method.toUpperCase()];
+    for (var i = 0, len = arr.length; i < len; ++i) {
+      if (arr[i].path.test(path)) return true;
+    }
+  }).map(function(method){
+    return method.toUpperCase();
+  });
+}
+
+/**
+ * Normalize the given path string,
+ * returning a regular expression.
+ *
+ * An empty array should be passed,
+ * which will contain the placeholder
+ * key names. For example "/user/:id" will
+ * then contain ["id"].
+ *
+ * @param  {String} path
+ * @param  {Array} keys
+ * @return {RegExp}
+ * @api private
+ */
+
+function normalizePath(path, keys) {
+  path = path
+    .concat('/?')
+    .replace(/\/\(/g, '(?:/')
+    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
+      keys.push(key);
+      slash = slash || '';
+      return ''
+        + (optional ? '' : slash)
+        + '(?:'
+        + (optional ? slash : '')
+        + (format || '') + (capture || '([^/]+?)') + ')'
+        + (optional || '');
+    })
+    .replace(/([\/.])/g, '\\$1')
+    .replace(/\*/g, '(.+)');
+  return new RegExp('^' + path + '$', 'i');
+}
+
+/**
+ * Attempt to match the given request to
+ * one of the routes. When successful
+ * a route function is returned.
+ *
+ * @param  {ServerRequest} req
+ * @param  {Object} routes
+ * @return {Function}
+ * @api private
+ */
+
+function match(req, routes, i) {
+  var captures
+    , method = req.method
+    , i = i || 0;
+  if ('HEAD' == method) method = 'GET';
+  if (routes = routes[method]) {
+    var url = parse(req.url)
+      , pathname = url.pathname;
+    for (var len = routes.length; i < len; ++i) {
+      var route = routes[i]
+        , fn = route.fn
+        , path = route.path
+        , keys = fn.keys = route.keys;
+      if (captures = path.exec(pathname)) {
+        fn.method = method;
+        fn.params = [];
+        for (var j = 1, len = captures.length; j < len; ++j) {
+          var key = keys[j-1],
+            val = typeof captures[j] === 'string'
+              ? decodeURIComponent(captures[j])
+              : captures[j];
+          if (key) {
+            fn.params[key] = val;
+          } else {
+            fn.params.push(val);
+          }
+        }
+        req._route_index = i;
+        return fn;
+      }
+    }
+  }
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session.js
new file mode 100644
index 0000000..7fbeb18
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session.js
@@ -0,0 +1,346 @@
+
+/*!
+ * Connect - session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Session = require('./session/session')
+  , MemoryStore = require('./session/memory')
+  , Cookie = require('./session/cookie')
+  , Store = require('./session/store')
+  , utils = require('./../utils')
+  , parse = require('url').parse
+  , crypto = require('crypto');
+
+// environment
+
+var env = process.env.NODE_ENV;
+
+/**
+ * Expose the middleware.
+ */
+
+exports = module.exports = session;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Store = Store;
+exports.Cookie = Cookie;
+exports.Session = Session;
+exports.MemoryStore = MemoryStore;
+
+/**
+ * Warning message for `MemoryStore` usage in production.
+ */
+
+var warning = 'Warning: connection.session() MemoryStore is not\n'
+  + 'designed for a production environment, as it will leak\n'
+  + 'memory, and obviously only work within a single process.';
+
+/**
+ * Default finger-printing function.
+ */
+
+function defaultFingerprint(req) {
+  var ua = req.headers['user-agent'] || '';
+  return ua.replace(/;?\schromeframe\/[\d\.]+/, '');
+};
+
+/**
+ * Paths to ignore.
+ */
+
+exports.ignore = [];
+
+/**
+ * Setup session store with the given `options`.
+ *
+ * Session data is _not_ saved in the cookie itself, however
+ * cookies are used, so we must use the [cookieParser()](middleware-cookieParser.html)
+ * middleware _before_ `session()`.
+ *
+ * Examples:
+ *
+ *     connect.createServer(
+ *         connect.cookieParser()
+ *       , connect.session({ secret: 'keyboard cat' })
+ *     );
+ *
+ * Options:
+ *
+ *   - `key`           cookie name defaulting to `connect.sid`
+ *   - `store`         Session store instance
+ *   - `fingerprint`   Custom fingerprint generating function
+ *   - `cookie`        Session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: 14400000 }`
+ *   - `secret`        Secret string used to compute hash
+ *
+ * Ignore Paths:
+ *
+ *  By default `/favicon.ico` is the only ignored path, all others
+ *  will utilize sessions, to manipulate the paths ignored, use
+ * `connect.session.ignore.push('/my/path')`. This works for _full_
+ *  pathnames only, not segments nor substrings.
+ *
+ *     connect.session.ignore.push('/robots.txt');
+ *
+ * ## req.session
+ *
+ *  To store or access session data, simply use the request property `req.session`,
+ *  which is (generally) serialized as JSON by the store, so nested objects 
+ *  are typically fine. For example below is a user-specific view counter:
+ *
+ *       connect(
+ *           connect.cookieParser()
+ *         , connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})
+ *         , connect.favicon()
+ *         , function(req, res, next){
+ *           var sess = req.session;
+ *           if (sess.views) {
+ *             res.setHeader('Content-Type', 'text/html');
+ *             res.write('<p>views: ' + sess.views + '</p>');
+ *             res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
+ *             res.end();
+ *             sess.views++;
+ *           } else {
+ *             sess.views = 1;
+ *             res.end('welcome to the session demo. refresh!');
+ *           }
+ *         }
+ *       ).listen(3000);
+ *
+ * ## Session#regenerate()
+ *
+ *  To regenerate the session simply invoke the method, once complete
+ *  a new SID and `Session` instance will be initialized at `req.session`.
+ *
+ *      req.session.regenerate(function(err){
+ *        // will have a new session here
+ *      });
+ *
+ * ## Session#destroy()
+ *
+ *  Destroys the session, removing `req.session`, will be re-generated next request.
+ *
+ *      req.session.destroy(function(err){
+ *        // cannot access session here
+ *      });
+ * 
+ * ## Session#reload()
+ *
+ *  Reloads the session data.
+ *
+ *      req.session.reload(function(err){
+ *        // session updated
+ *      });
+ *
+ * ## Session#save()
+ *
+ *  Save the session.
+ *
+ *      req.session.save(function(err){
+ *        // session saved
+ *      });
+ *
+ * ## Session#touch()
+ *
+ *   Updates the `.maxAge`, and `.lastAccess` properties. Typically this is
+ *   not necessary to call, as the session middleware does this for you.
+ *
+ * ## Session#cookie
+ *
+ *  Each session has a unique cookie object accompany it. This allows
+ *  you to alter the session cookie per visitor. For example we can
+ *  set `req.session.cookie.expires` to `false` to enable the cookie
+ *  to remain for only the duration of the user-agent.
+ *
+ * ## Session#maxAge
+ *
+ *  Alternatively `req.session.cookie.maxAge` will return the time
+ *  remaining in milliseconds, which we may also re-assign a new value
+ *  to adjust the `.expires` property appropriately. The following
+ *  are essentially equivalent
+ *
+ *     var hour = 3600000;
+ *     req.session.cookie.expires = new Date(Date.now() + hour);
+ *     req.session.cookie.maxAge = hour;
+ *
+ * For example when `maxAge` is set to `60000` (one minute), and 30 seconds
+ * has elapsed it will return `30000` until the current request has completed,
+ * at which time `req.session.touch()` is called to update `req.session.lastAccess`,
+ * and reset `req.session.maxAge` to its original value.
+ *
+ *     req.session.cookie.maxAge;
+ *     // => 30000
+ *
+ * Session Store Implementation:
+ *
+ * Every session store _must_ implement the following methods
+ *
+ *    - `.get(sid, callback)`
+ *    - `.set(sid, session, callback)`
+ *    - `.destroy(sid, callback)`
+ *
+ * Recommended methods include, but are not limited to:
+ *
+ *    - `.length(callback)`
+ *    - `.clear(callback)`
+ *
+ * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+function session(options){
+  var options = options || {}
+    , key = options.key || 'connect.sid'
+    , secret = options.secret
+    , store = options.store || new MemoryStore
+    , fingerprint = options.fingerprint || defaultFingerprint
+    , cookie = options.cookie;
+
+  // notify user that this store is not
+  // meant for a production environment
+  if ('production' == env && store instanceof MemoryStore) {
+    console.warn(warning);
+  }
+
+  // ensure secret is present
+  if (!secret) {
+    throw new Error('connect.session({ secret: "string" }) required for security');
+  }
+
+  // session hashing function
+  store.hash = function(req, base) {
+    return crypto
+      .createHmac('sha256', secret)
+      .update(base + fingerprint(req))
+      .digest('base64')
+      .replace(/=*$/, '');
+  };
+
+  // generates the new session
+  store.generate = function(req){
+    var base = utils.uid(24);
+    var sessionID = base + '.' + store.hash(req, base);
+    req.sessionID = sessionID;
+    req.session = new Session(req);
+    req.session.cookie = new Cookie(cookie);
+  };
+
+  return function session(req, res, next) {
+    // self-awareness
+    if (req.session) return next();
+
+    // parse url
+    var url = parse(req.url)
+      , path = url.pathname;
+
+    // ignorable paths
+    if (~exports.ignore.indexOf(path)) return next();
+
+    // expose store
+    req.sessionStore = store;
+
+    // proxy writeHead() to Set-Cookie
+    var writeHead = res.writeHead;
+    res.writeHead = function(status, headers){
+      if (req.session) {
+        var cookie = req.session.cookie;
+        // only send secure session cookies when there is a secure connection.
+        // proxySecure is a custom attribute to allow for a reverse proxy
+        // to handle SSL connections and to communicate to connect over HTTP that
+        // the incoming connection is secure.
+        var secured = cookie.secure && (req.connection.encrypted || req.connection.proxySecure);
+        if (secured || !cookie.secure) {
+          res.setHeader('Set-Cookie', cookie.serialize(key, req.sessionID));
+        }
+      }
+
+      res.writeHead = writeHead;
+      return res.writeHead(status, headers);
+    };
+
+    // proxy end() to commit the session
+    var end = res.end;
+    res.end = function(data, encoding){
+      res.end = end;
+      if (req.session) {
+        // HACK: ensure Set-Cookie for implicit writeHead()
+        if (!res._header) res._implicitHeader();
+        req.session.resetMaxAge();
+        req.session.save(function(){
+          res.end(data, encoding);
+        });
+      } else {
+        res.end(data, encoding);
+      }
+    };
+
+    // session hashing
+    function hash(base) {
+      return store.hash(req, base);
+    }
+
+    // generate the session
+    function generate() {
+      store.generate(req);
+    }
+
+    // get the sessionID from the cookie
+    req.sessionID = req.cookies[key];
+
+    // make a new session if the browser doesn't send a sessionID
+    if (!req.sessionID) {
+      generate();
+      next();
+      return;
+    }
+
+    // check the fingerprint
+    var parts = req.sessionID.split('.');
+    if (parts[1] != hash(parts[0])) {
+      generate();
+      next();
+      return;
+    }
+
+    // generate the session object
+    var pause = utils.pause(req);
+    store.get(req.sessionID, function(err, sess){
+      // proxy to resume() events
+      var _next = next;
+      next = function(err){
+        _next(err);
+        pause.resume();
+      }
+
+      // error handling
+      if (err) {
+        if ('ENOENT' == err.code) {
+          generate();
+          next();
+        } else {
+          next(err);
+        }
+      // no session
+      } else if (!sess) {
+        generate();
+        next();
+      // populate req.session
+      } else {
+        store.createSession(req, sess);
+        next();
+      }
+    });
+  };
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js
new file mode 100644
index 0000000..793c2e9
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js
@@ -0,0 +1,126 @@
+
+/*!
+ * Connect - session - Cookie
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils');
+
+/**
+ * Initialize a new `Cookie` with the given `options`.
+ *
+ * @param {Object} options
+ * @api private
+ */
+
+var Cookie = module.exports = function Cookie(options) {
+  this.path = '/';
+  this.httpOnly = true;
+  this.maxAge = 14400000;
+  if (options) utils.merge(this, options);
+  this.originalMaxAge = undefined == this.originalMaxAge
+    ? this.maxAge
+    : this.originalMaxAge;
+};
+
+/**
+ * Prototype.
+ */
+
+Cookie.prototype = {
+
+  /**
+   * Set expires `date`.
+   *
+   * @param {Date} date
+   * @api public
+   */
+  
+  set expires(date) {
+    this._expires = date;
+    this.originalMaxAge = this.maxAge;
+  },
+
+  /**
+   * Get expires `date`.
+   *
+   * @return {Date}
+   * @api public
+   */
+
+  get expires() {
+    return this._expires;
+  },
+  
+  /**
+   * Set expires via max-age in `ms`.
+   *
+   * @param {Number} ms
+   * @api public
+   */
+  
+  set maxAge(ms) {
+    this.expires = 'number' == typeof ms
+      ? new Date(Date.now() + ms)
+      : ms;
+  },
+
+  /**
+   * Get expires max-age in `ms`.
+   *
+   * @return {Number}
+   * @api public
+   */
+
+  get maxAge() {
+    return this.expires instanceof Date
+      ? this.expires.valueOf() - Date.now()
+      : this.expires;
+  },
+
+  /**
+   * Return cookie data object.
+   *
+   * @return {Object}
+   * @api private
+   */
+
+  get data() {
+    return {
+        originalMaxAge: this.originalMaxAge
+      , expires: this._expires
+      , secure: this.secure
+      , httpOnly: this.httpOnly
+      , domain: this.domain
+      , path: this.path
+    }
+  },
+
+  /**
+   * Return a serialized cookie string.
+   *
+   * @return {String}
+   * @api public
+   */
+
+  serialize: function(name, val){
+    return utils.serializeCookie(name, val, this.data);
+  },
+
+  /**
+   * Return JSON representation of this cookie.
+   *
+   * @return {Object}
+   * @api private
+   */
+  
+  toJSON: function(){
+    return this.data;
+  }
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/memory.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/memory.js
new file mode 100644
index 0000000..ec569f5
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/memory.js
@@ -0,0 +1,131 @@
+
+/*!
+ * Connect - session - MemoryStore
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Store = require('./store')
+  , utils = require('../../utils')
+  , Session = require('./session');
+
+/**
+ * Initialize a new `MemoryStore`.
+ *
+ * @api public
+ */
+
+var MemoryStore = module.exports = function MemoryStore() {
+  this.sessions = {};
+};
+
+/**
+ * Inherit from `Store.prototype`.
+ */
+
+MemoryStore.prototype.__proto__ = Store.prototype;
+
+/**
+ * Attempt to fetch session by the given `sid`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.get = function(sid, fn){
+  var self = this;
+  process.nextTick(function(){
+    var expires
+      , sess = self.sessions[sid];
+    if (sess) {
+      sess = JSON.parse(sess);
+      expires = 'string' == typeof sess.cookie.expires
+        ? new Date(sess.cookie.expires)
+        : sess.cookie.expires;
+      if (!expires || new Date < expires) {
+        fn(null, sess);
+      } else {
+        self.destroy(sid, fn);
+      }
+    } else {
+      fn();
+    }
+  });
+};
+
+/**
+ * Commit the given `sess` object associated with the given `sid`.
+ *
+ * @param {String} sid
+ * @param {Session} sess
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.set = function(sid, sess, fn){
+  var self = this;
+  process.nextTick(function(){
+    self.sessions[sid] = JSON.stringify(sess);
+    fn && fn();
+  });
+};
+
+/**
+ * Destroy the session associated with the given `sid`.
+ *
+ * @param {String} sid
+ * @api public
+ */
+
+MemoryStore.prototype.destroy = function(sid, fn){
+  var self = this;
+  process.nextTick(function(){
+    delete self.sessions[sid];
+    fn && fn();
+  });
+};
+
+/**
+ * Invoke the given callback `fn` with all active sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.all = function(fn){
+  var arr = []
+    , keys = Object.keys(this.sessions);
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    arr.push(this.sessions[keys[i]]);
+  }
+  fn(null, arr);
+};
+
+/**
+ * Clear all sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.clear = function(fn){
+  this.sessions = {};
+  fn && fn();
+};
+
+/**
+ * Fetch number of sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.length = function(fn){
+  fn(null, Object.keys(this.sessions).length);
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/session.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/session.js
new file mode 100644
index 0000000..4e7e1a6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/session.js
@@ -0,0 +1,137 @@
+
+/*!
+ * Connect - session - Session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils')
+  , Cookie = require('./cookie');
+
+/**
+ * Create a new `Session` with the given request and `data`.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} data
+ * @api private
+ */
+
+var Session = module.exports = function Session(req, data) {
+  Object.defineProperty(this, 'req', { value: req });
+  Object.defineProperty(this, 'id', { value: req.sessionID });
+  if ('object' == typeof data) {
+    utils.merge(this, data);
+  } else {
+    this.lastAccess = Date.now();
+  }
+};
+
+/**
+ * Update `.lastAccess` timestamp,
+ * and reset `.cookie.maxAge` to prevent
+ * the cookie from expiring when the
+ * session is still active.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.touch = function(){
+  return this
+    .resetLastAccess()
+    .resetMaxAge();
+};
+
+/**
+ * Update `.lastAccess` timestamp.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.resetLastAccess = function(){
+  this.lastAccess = Date.now();
+  return this;
+};
+
+/**
+ * Reset `.maxAge` to `.originalMaxAge`.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.resetMaxAge = function(){
+  this.cookie.maxAge = this.cookie.originalMaxAge;
+  return this;
+};
+
+/**
+ * Save the session data with optional callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.save = function(fn){
+  this.req.sessionStore.set(this.id, this, fn || function(){});
+  return this;
+};
+
+/**
+ * Re-loads the session data _without_ altering
+ * the maxAge or lastAccess properties. Invokes the
+ * callback `fn(err)`, after which time if no exception
+ * has occurred the `req.session` property will be
+ * a new `Session` object, although representing the
+ * same session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.reload = function(fn){
+  var req = this.req
+    , store = this.req.sessionStore;
+  store.get(this.id, function(err, sess){
+    if (err) return fn(err);
+    if (!sess) return fn(new Error('failed to load session'));
+    store.createSession(req, sess);
+    fn();
+  });
+  return this;
+};
+
+/**
+ * Destroy `this` session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.destroy = function(fn){
+  delete this.req.session;
+  this.req.sessionStore.destroy(this.id, fn);
+  return this;
+};
+
+/**
+ * Regenerate this request's session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.regenerate = function(fn){
+  this.req.sessionStore.regenerate(this.req, fn);
+  return this;
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/store.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/store.js
new file mode 100644
index 0000000..6a3d47d
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/session/store.js
@@ -0,0 +1,87 @@
+
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+  , Session = require('./session')
+  , Cookie = require('./cookie')
+  , utils = require('../../utils');
+
+/**
+ * Initialize abstract `Store`.
+ *
+ * @api private
+ */
+
+var Store = module.exports = function Store(options){};
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Store.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Re-generate the given requests's session.
+ *
+ * @param {IncomingRequest} req
+ * @return {Function} fn
+ * @api public
+ */
+
+Store.prototype.regenerate = function(req, fn){
+  var self = this;
+  this.destroy(req.sessionID, function(err){
+    self.generate(req);
+    fn(err);
+  });
+};
+
+/**
+ * Load a `Session` instance via the given `sid`
+ * and invoke the callback `fn(err, sess)`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+Store.prototype.load = function(sid, fn){
+  var self = this;
+  this.get(sid, function(err, sess){
+    if (err) return fn(err);
+    if (!sess) return fn();
+    var req = { sessionID: sid, sessionStore: self };
+    sess = self.createSession(req, sess, false);
+    fn(null, sess);
+  });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess, update){
+  var expires = sess.cookie.expires
+    , orig = sess.cookie.originalMaxAge
+    , update = null == update ? true : false;
+  sess.cookie = new Cookie(sess.cookie);
+  if ('string' == typeof expires) sess.cookie.expires = new Date(expires);
+  sess.cookie.originalMaxAge = orig;
+  req.session = new Session(req, sess);
+  if (update) req.session.resetLastAccess();
+  return req.session;
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/static.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/static.js
new file mode 100644
index 0000000..b9c2c86
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/static.js
@@ -0,0 +1,225 @@
+
+/*!
+ * Connect - staticProvider
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , path = require('path')
+  , join = path.join
+  , basename = path.basename
+  , normalize = path.normalize
+  , utils = require('../utils')
+  , Buffer = require('buffer').Buffer
+  , parse = require('url').parse
+  , mime = require('mime');
+
+/**
+ * Static file server with the given `root` path.
+ *
+ * Examples:
+ *
+ *     var oneDay = 86400000;
+ *
+ *     connect(
+ *       connect.static(__dirname + '/public')
+ *     ).listen(3000);
+ *
+ *     connect(
+ *       connect.static(__dirname + '/public', { maxAge: oneDay })
+ *     ).listen(3000);
+ *
+ * Options:
+ *
+ *    - `maxAge`   Browser cache maxAge in milliseconds. defaults to 0
+ *    - `hidden`   Allow transfer of hidden files. defaults to false
+ *    - `redirect`   Redirect to trailing "/" when the pathname is a dir
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function static(root, options){
+  options = options || {};
+
+  // root required
+  if (!root) throw new Error('static() root path required');
+  options.root = root;
+
+  return function static(req, res, next) {
+    options.path = req.url;
+    options.getOnly = true;
+    send(req, res, next, options);
+  };
+};
+
+/**
+ * Expose mime module.
+ */
+
+exports.mime = mime;
+
+/**
+ * Respond with 416  "Requested Range Not Satisfiable"
+ *
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+function invalidRange(res) {
+  var body = 'Requested Range Not Satisfiable';
+  res.setHeader('Content-Type', 'text/plain');
+  res.setHeader('Content-Length', body.length);
+  res.statusCode = 416;
+  res.end(body);
+}
+
+/**
+ * Attempt to tranfer the requseted file to `res`.
+ *
+ * @param {ServerRequest}
+ * @param {ServerResponse}
+ * @param {Function} next
+ * @param {Object} options
+ * @api private
+ */
+
+var send = exports.send = function(req, res, next, options){
+  options = options || {};
+  if (!options.path) throw new Error('path required');
+
+  // setup
+  var maxAge = options.maxAge || 0
+    , ranges = req.headers.range
+    , head = 'HEAD' == req.method
+    , get = 'GET' == req.method
+    , root = options.root ? normalize(options.root) : null
+    , redirect = false === options.redirect ? false : true
+    , getOnly = options.getOnly
+    , fn = options.callback
+    , hidden = options.hidden
+    , done;
+
+  // replace next() with callback when available
+  if (fn) next = fn;
+
+  // ignore non-GET requests
+  if (getOnly && !get && !head) return next();
+
+  // parse url
+  var url = parse(options.path)
+    , path = decodeURIComponent(url.pathname)
+    , type;
+
+  // null byte(s)
+  if (~path.indexOf('\0')) return utils.badRequest(res);
+
+  // when root is not given, consider .. malicious
+  if (!root && ~path.indexOf('..')) return utils.forbidden(res);
+
+  // join / normalize from optional root dir
+  path = normalize(join(root, path));
+
+  // malicious path
+  if (root && 0 != path.indexOf(root)) return fn
+    ? fn(new Error('Forbidden'))
+    : utils.forbidden(res);
+
+  // index.html support
+  if (normalize('/') == path[path.length - 1]) path += 'index.html';
+
+  // "hidden" file
+  if (!hidden && '.' == basename(path)[0]) return next();
+
+  fs.stat(path, function(err, stat){
+    // mime type
+    type = mime.lookup(path);
+
+    // ignore ENOENT
+    if (err) {
+      if (fn) return fn(err);
+      return 'ENOENT' == err.code
+        ? next()
+        : next(err);
+    // redirect directory in case index.html is present
+    } else if (stat.isDirectory()) {
+      if (!redirect) return next();
+      res.statusCode = 301;
+      res.setHeader('Location', url.pathname + '/');
+      res.end('Redirecting to ' + url.pathname + '/');
+      return;
+    }
+
+    // header fields
+    if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
+    if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
+    if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
+    if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
+    if (!res.getHeader('content-type')) {
+      var charset = mime.charsets.lookup(type);
+      res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+    }
+    res.setHeader('Accept-Ranges', 'bytes');
+
+    // conditional GET support
+    if (utils.conditionalGET(req)) {
+      if (!utils.modified(req, res)) {
+        req.emit('static');
+        return utils.notModified(res);
+      }
+    }
+
+    var opts = {};
+    var chunkSize = stat.size;
+
+    // we have a Range request
+    if (ranges) {
+      ranges = utils.parseRange(stat.size, ranges);
+      // valid
+      if (ranges) {
+        // TODO: stream options
+        // TODO: multiple support
+        opts.start = ranges[0].start;
+        opts.end = ranges[0].end;
+        chunkSize = opts.end - opts.start + 1;
+        res.statusCode = 206;
+        res.setHeader('Content-Range', 'bytes '
+          + opts.start
+          + '-'
+          + opts.end
+          + '/'
+          + stat.size);
+      // invalid
+      } else {
+        return fn
+          ? fn(new Error('Requested Range Not Satisfiable'))
+          : invalidRange(res);
+      }
+    }
+
+    res.setHeader('Content-Length', chunkSize);
+
+    // transfer
+    if (head) return res.end();
+
+    // stream
+    var stream = fs.createReadStream(path, opts);
+    req.emit('static', stream);
+    stream.pipe(res);
+
+    // callback
+    if (fn) {
+      function callback(err) { done || fn(err); done = true }
+      req.on('close', callback);
+      stream.on('end', callback);
+    }
+  });
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js
new file mode 100644
index 0000000..9ea8eb7
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js
@@ -0,0 +1,175 @@
+
+/*!
+ * Connect - staticCache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , utils = require('../utils')
+  , Cache = require('../cache')
+  , url = require('url')
+  , fs = require('fs');
+
+/**
+ * Enables a memory cache layer on top of
+ * the `static()` middleware, serving popular
+ * static files.
+ *
+ * By default a maximum of 128 objects are
+ * held in cache, with a max of 256k each,
+ * totalling ~32mb.
+ *
+ * A Least-Recently-Used (LRU) cache algo
+ * is implemented through the `Cache` object,
+ * simply rotating cache objects as they are
+ * hit. This means that increasingly popular
+ * objects maintain their positions while
+ * others get shoved out of the stack and
+ * garbage collected.
+ *
+ * Benchmarks:
+ *
+ *     static(): 2700 rps
+ *     node-static: 5300 rps
+ *     static() + staticCache(): 7500 rps
+ *
+ * Options:
+ *
+ *   - `maxObjects`  max cache objects [128]
+ *   - `maxLength`  max cache object length 256kb
+ *
+ * @param {Type} name
+ * @return {Type}
+ * @api public
+ */
+
+module.exports = function staticCache(options){
+  var options = options || {}
+    , cache = new Cache(options.maxObjects || 128)
+    , maxlen = options.maxLength || 1024 * 256;
+
+  return function staticCache(req, res, next){
+    var path = url.parse(req.url).pathname
+      , ranges = req.headers.range
+      , hit = cache.get(path)
+      , hitCC
+      , uaCC
+      , header
+      , age;
+
+    // cache static
+    req.on('static', function(stream){
+      var headers = res._headers
+        , cc = utils.parseCacheControl(headers['cache-control'] || '')
+        , contentLength = headers['content-length']
+        , hit;
+
+      // ignore larger files
+      if (!contentLength || contentLength > maxlen) return;
+
+      // dont cache items we shouldn't be
+      if ( cc['no-cache']
+        || cc['no-store']
+        || cc['private']
+        || cc['must-revalidate']) return;
+
+      // if already in cache then validate
+      if (hit = cache.get(path)){
+        if (headers.etag == hit[0].etag) {
+          hit[0].date = new Date;
+          return;
+        } else {
+          cache.remove(path);
+        }
+      }
+
+      // validation notifiactions don't contain a steam
+      if (null == stream) return;
+
+      // add the cache object
+      var arr = cache.add(path);
+      arr.push(headers);
+
+      // store the chunks
+      stream.on('data', function(chunk){
+        arr.push(chunk);
+      });
+
+      // flag it as complete
+      stream.on('end', function(){
+        arr.complete = true;
+      });
+    });
+
+    // cache hit, doesnt support range requests
+    if (hit && hit.complete && !ranges) {
+      header = utils.merge({}, hit[0]);
+      header.Age = age = (new Date - new Date(header.date)) / 1000 | 0;
+      header.date = new Date().toUTCString();
+
+      // parse cache-controls
+      hitCC = utils.parseCacheControl(header['cache-control'] || '');
+      uaCC = utils.parseCacheControl(req.headers['cache-control'] || '');
+
+      // check if we must revalidate(bypass)
+      if (hitCC['no-cache'] || uaCC['no-cache']) return next();
+
+      // check freshness of entity
+      if (isStale(hitCC, age) || isStale(uaCC, age)) return next();
+
+      // conditional GET support
+      if (utils.conditionalGET(req)) {
+        if (!utils.modified(req, res, header)) {
+          header['content-length'] = 0;
+          res.writeHead(304, header);
+          return res.end();
+        }
+      }
+
+      // HEAD support
+      if ('HEAD' == req.method) {
+        header['content-length'] = 0;
+        res.writeHead(200, header);
+        return res.end();
+      }
+
+      // respond with cache
+      res.writeHead(200, header);
+
+      // backpressure
+      function write(i) {
+        var buf = hit[i];
+        if (!buf) return res.end();
+        if (false === res.write(buf)) {
+          res.once('drain', function(){
+            write(++i);
+          });
+        } else {
+          write(++i);
+        }
+      }
+
+      return write(1);
+    }
+
+    next();
+  }
+};
+
+/**
+ * Check if cache item is stale
+ *
+ * @param {Object} cc
+ * @param {Number} age
+ * @return {Boolean}
+ * @api private
+ */
+
+function isStale(cc, age) {
+  return cc['max-age'] && cc['max-age'] <= age;
+}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/middleware/vhost.js b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/vhost.js
new file mode 100644
index 0000000..913d756
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/middleware/vhost.js
@@ -0,0 +1,44 @@
+
+/*!
+ * Connect - vhost
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Setup vhost for the given `hostname` and `server`.
+ *
+ * Examples:
+ *
+ *     connect(
+ *       connect.vhost('foo.com',
+ *         connect.createServer(...middleware...)
+ *       ),
+ *       connect.vhost('bar.com',
+ *         connect.createServer(...middleware...)
+ *       )
+ *     );
+ *
+ * @param {String} hostname
+ * @param {Server} server
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function vhost(hostname, server){
+  if (!hostname) throw new Error('vhost hostname required');
+  if (!server) throw new Error('vhost server required');
+  var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$');
+  if (server.onvhost) server.onvhost(hostname);
+  return function vhost(req, res, next){
+    if (!req.headers.host) return next();
+    var host = req.headers.host.split(':')[0];
+    if (req.subdomains = regexp.exec(host)) {
+      req.subdomains = req.subdomains[0].split('.').slice(0, -1);
+      server.emit("request", req, res);
+    } else {
+      next();
+    }
+  };
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/patch.js b/weinre.server/node_modules/express/node_modules/connect/lib/patch.js
new file mode 100644
index 0000000..a6ff297
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/patch.js
@@ -0,0 +1,79 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , res = http.OutgoingMessage.prototype;
+
+// original setHeader()
+
+var setHeader = res.setHeader;
+
+// original _renderHeaders()
+
+var _renderHeaders = res._renderHeaders;
+
+if (res._hasConnectPatch) return;
+
+/**
+ * Provide a public "header sent" flag
+ * until node does.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+res.__defineGetter__('headerSent', function(){
+  return this._headerSent;
+});
+
+/**
+ * Set header `field` to `val`, special-casing
+ * the `Set-Cookie` field for multiple support.
+ *
+ * @param {String} field
+ * @param {String} val
+ * @api public
+ */
+
+res.setHeader = function(field, val){
+  var key = field.toLowerCase()
+    , prev;
+
+  // special-case Set-Cookie
+  if (this._headers && 'set-cookie' == key) {
+    if (prev = this.getHeader(field)) {
+      val = Array.isArray(prev)
+        ? prev.concat(val)
+        : [prev, val];
+    }
+  // charset
+  } else if ('content-type' == key && this.charset) {
+    val += '; charset=' + this.charset;
+  }
+
+  return setHeader.call(this, field, val);
+};
+
+/**
+ * Proxy `res.end()` to expose a 'header' event,
+ * allowing arbitrary augmentation before the header
+ * fields are written to the socket.
+ *
+ * NOTE: this _only_ supports node's progressive header
+ * field API aka `res.setHeader()`.
+ */
+
+res._renderHeaders = function(){
+  this.emit('header');
+  return _renderHeaders.call(this);
+};
+
+res._hasConnectPatch = true;
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/directory.html b/weinre.server/node_modules/express/node_modules/connect/lib/public/directory.html
new file mode 100644
index 0000000..15164bb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/directory.html
@@ -0,0 +1,75 @@
+<html>
+  <head>
+    <title>listing directory {directory}</title>
+    <style>{style}</style>
+    <script>
+      function $(id){
+        var el = 'string' == typeof id
+          ? document.getElementById(id)
+          : id;
+
+        el.on = function(event, fn){
+          if ('content loaded' == event) event = 'DOMContentLoaded';
+          el.addEventListener(event, fn, false);
+        };
+
+        el.all = function(selector){
+          return $(el.querySelectorAll(selector));
+        };
+
+        el.each = function(fn){
+          for (var i = 0, len = el.length; i < len; ++i) {
+            fn($(el[i]), i);
+          }
+        };
+
+        el.getClasses = function(){
+          return this.getAttribute('class').split(/\s+/);
+        };
+
+        el.addClass = function(name){
+          var classes = this.getAttribute('class');
+          el.setAttribute('class', classes
+            ? classes + ' ' + name
+            : name);
+        };
+
+        el.removeClass = function(name){
+          var classes = this.getClasses().filter(function(curr){
+            return curr != name;
+          });
+          this.setAttribute('class', classes);
+        };
+
+        return el;
+      }
+
+      function search() {
+        var str = $('search').value
+          , links = $('files').all('a');
+
+        links.each(function(link){
+          var text = link.textContent;
+
+          if ('..' == text) return;
+          if (str.length && ~text.indexOf(str)) {
+            link.addClass('highlight');
+          } else {
+            link.removeClass('highlight');
+          }
+        });
+      }
+
+      $(window).on('content loaded', function(){
+        $('search').on('keyup', search);
+      });
+    </script>
+  </head>
+  <body class="directory">
+    <input id="search" type="text" placeholder="Search" autocomplete="off" />
+    <div id="wrapper">
+      <h1>{linked-path}</h1>
+      {files}
+    </div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/error.html b/weinre.server/node_modules/express/node_modules/connect/lib/public/error.html
new file mode 100644
index 0000000..34e0df5
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/error.html
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>{error}</title>
+    <style>{style}</style>
+  </head>
+  <body>
+    <div id="wrapper">
+      <h1>{title}</h1>
+      <h2><em>500</em> {error}</h2>
+      <ul id="stacktrace">{stack}</ul>
+    </div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/favicon.ico b/weinre.server/node_modules/express/node_modules/connect/lib/public/favicon.ico
new file mode 100644
index 0000000..895fc96
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/favicon.ico
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page.png
new file mode 100755
index 0000000..03ddd79
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_add.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_add.png
new file mode 100755
index 0000000..d5bfa07
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_add.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png
new file mode 100755
index 0000000..89ee2da
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_code.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_code.png
new file mode 100755
index 0000000..f7ea904
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_code.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png
new file mode 100755
index 0000000..195dc6d
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png
new file mode 100755
index 0000000..3141467
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png
new file mode 100755
index 0000000..046811e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_error.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_error.png
new file mode 100755
index 0000000..f07f449
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_error.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png
new file mode 100755
index 0000000..eb6158e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_find.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_find.png
new file mode 100755
index 0000000..2f19388
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_find.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png
new file mode 100755
index 0000000..8e83281
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_go.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_go.png
new file mode 100755
index 0000000..80fe1ed
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_go.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_green.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_green.png
new file mode 100755
index 0000000..de8e003
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_green.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_key.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_key.png
new file mode 100755
index 0000000..d6626cb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_key.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png
new file mode 100755
index 0000000..7e56870
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_link.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_link.png
new file mode 100755
index 0000000..312eab0
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_link.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png
new file mode 100755
index 0000000..246a2f0
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png
new file mode 100755
index 0000000..968f073
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_red.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_red.png
new file mode 100755
index 0000000..0b18247
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_red.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png
new file mode 100755
index 0000000..cf347c7
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_save.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_save.png
new file mode 100755
index 0000000..caea546
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_save.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white.png
new file mode 100755
index 0000000..8b8b1ca
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png
new file mode 100755
index 0000000..8f8095e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png
new file mode 100755
index 0000000..159b240
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png
new file mode 100755
index 0000000..aa23dde
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png
new file mode 100755
index 0000000..34a05cc
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png
new file mode 100755
index 0000000..f501a59
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png
new file mode 100755
index 0000000..848bdaf
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png
new file mode 100755
index 0000000..0c76bd1
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png
new file mode 100755
index 0000000..87a6914
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png
new file mode 100755
index 0000000..c66011f
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png
new file mode 100755
index 0000000..2b6b100
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png
new file mode 100755
index 0000000..a9f31a2
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png
new file mode 100755
index 0000000..a87cf84
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png
new file mode 100755
index 0000000..ffb8fc9
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png
new file mode 100755
index 0000000..0a7d6f4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png
new file mode 100755
index 0000000..bddba1f
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png
new file mode 100755
index 0000000..af1ecaf
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png
new file mode 100755
index 0000000..4cc537a
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png
new file mode 100755
index 0000000..b93e776
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png
new file mode 100755
index 0000000..9fc5a0a
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png
new file mode 100755
index 0000000..b977d7e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png
new file mode 100755
index 0000000..5818436
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png
new file mode 100755
index 0000000..5769120
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png
new file mode 100755
index 0000000..8d719df
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png
new file mode 100755
index 0000000..106f5aa
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png
new file mode 100755
index 0000000..e4a1ecb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png
new file mode 100755
index 0000000..7e62a92
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png
new file mode 100755
index 0000000..e902abb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png
new file mode 100755
index 0000000..1d2d0a4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png
new file mode 100755
index 0000000..d616484
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png
new file mode 100755
index 0000000..7215d1e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png
new file mode 100755
index 0000000..bf7bd1c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png
new file mode 100755
index 0000000..f6b74cc
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png
new file mode 100755
index 0000000..d3fffb6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png
new file mode 100755
index 0000000..a65bcb3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png
new file mode 100755
index 0000000..23a37b8
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png
new file mode 100755
index 0000000..f907e44
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png
new file mode 100755
index 0000000..5b2cbb3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png
new file mode 100755
index 0000000..7868a25
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png
new file mode 100755
index 0000000..134b669
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png
new file mode 100755
index 0000000..c4eff03
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png
new file mode 100755
index 0000000..884ffd6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png
new file mode 100755
index 0000000..f59b7c4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png
new file mode 100755
index 0000000..44084ad
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png
new file mode 100755
index 0000000..3a1441c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png
new file mode 100755
index 0000000..e770829
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png
new file mode 100755
index 0000000..813f712
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png
new file mode 100755
index 0000000..d9cf132
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png
new file mode 100755
index 0000000..52699bf
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png
new file mode 100755
index 0000000..4a05955
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png
new file mode 100755
index 0000000..a0a433d
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png
new file mode 100755
index 0000000..1eb8809
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png
new file mode 100755
index 0000000..ae8ecbf
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png
new file mode 100755
index 0000000..6ed2490
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png
new file mode 100755
index 0000000..fecadd0
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png
new file mode 100755
index 0000000..fd4bbcc
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_word.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_word.png
new file mode 100755
index 0000000..834cdfa
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_word.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_world.png b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_world.png
new file mode 100755
index 0000000..b8895dd
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/icons/page_world.png
Binary files differ
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/public/style.css b/weinre.server/node_modules/express/node_modules/connect/lib/public/style.css
new file mode 100644
index 0000000..32b6507
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/public/style.css
@@ -0,0 +1,141 @@
+body {
+  margin: 0;
+  padding: 80px 100px;
+  font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
+  background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
+  background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9);
+  background-repeat: no-repeat;
+  color: #555;
+  -webkit-font-smoothing: antialiased;
+}
+h1, h2, h3 {
+  margin: 0;
+  font-size: 22px;
+  color: #343434;
+}
+h1 em, h2 em {
+  padding: 0 5px;
+  font-weight: normal;
+}
+h1 {
+  font-size: 60px;
+}
+h2 {
+	margin-top: 10px;
+}
+h3 {
+  margin: 5px 0 10px 0;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #eee;
+  font-size: 18px;
+}
+ul {
+  margin: 0;
+  padding: 0;
+}
+ul li {
+  margin: 5px 0;
+  padding: 3px 8px;
+  list-style: none;
+}
+ul li:hover {
+  cursor: pointer;
+  color: #2e2e2e;
+}
+ul li .path {
+  padding-left: 5px;
+  font-weight: bold;
+}
+ul li .line {
+  padding-right: 5px;
+  font-style: italic;
+}
+ul li:first-child .path {
+  padding-left: 0;
+}
+p {
+  line-height: 1.5;
+}
+a {
+  color: #555;
+  text-decoration: none;
+}
+a:hover {
+  color: #303030;
+}
+#stacktrace {
+	margin-top: 15px;
+}
+.directory h1 {
+  margin-bottom: 15px;
+  font-size: 18px;
+}
+ul#files {
+  width: 100%;
+  height: 500px;
+}
+ul#files li {
+  padding: 0;
+}
+ul#files li img {
+  position: absolute;
+  top: 5px;
+  left: 5px;
+}
+ul#files li a {
+   position: relative;
+  display: block;
+  margin: 1px;
+  width: 30%;
+  height: 25px;
+  line-height: 25px;
+  text-indent: 8px;
+  float: left;
+  border: 1px solid transparent;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+ul#files li a.icon {
+  text-indent: 25px;
+}
+ul#files li a:focus,
+ul#files li a:hover {
+  outline: none;
+  background: rgba(255,255,255,0.65);
+  border: 1px solid #ececec;
+}
+ul#files li a.highlight {
+  -webkit-transition: background .4s ease-in-out;
+  background: #ffff4f;
+  border-color: #E9DC51;
+}
+#search {
+  display: block;
+  position: fixed;
+  top: 20px;
+  right: 20px;
+  width: 90px;
+  -webkit-transition: width ease 0.2s, opacity ease 0.4s;
+  -moz-transition: width ease 0.2s, opacity ease 0.4s;
+  -webkit-border-radius: 32px;
+  -moz-border-radius: 32px;
+  -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+  -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+  -webkit-font-smoothing: antialiased;
+  text-align: left;
+  font: 13px "Helvetica Neue", Arial, sans-serif;
+  padding: 4px 10px;
+  border: none;
+  background: transparent;
+  margin-bottom: 0;
+  outline: none;
+  opacity: 0.7;
+  color: #888;
+}
+#search:focus {
+  width: 120px;
+  opacity: 1.0; 
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/lib/utils.js b/weinre.server/node_modules/express/node_modules/connect/lib/utils.js
new file mode 100644
index 0000000..d0bc172
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/lib/utils.js
@@ -0,0 +1,451 @@
+
+/*!
+ * Connect - utils
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto')
+  , Path = require('path')
+  , fs = require('fs');
+
+/**
+ * Flatten the given `arr`.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.flatten = function(arr, ret){
+  var ret = ret || []
+    , len = arr.length;
+  for (var i = 0; i < len; ++i) {
+    if (Array.isArray(arr[i])) {
+      exports.flatten(arr[i], ret);
+    } else {
+      ret.push(arr[i]);
+    }
+  }
+  return ret;
+};
+
+/**
+ * Return md5 hash of the given string and optional encoding,
+ * defaulting to hex.
+ *
+ *     utils.md5('wahoo');
+ *     // => "e493298061761236c96b02ea6aa8a2ad"
+ *
+ * @param {String} str
+ * @param {String} encoding
+ * @return {String}
+ * @api public
+ */
+
+exports.md5 = function(str, encoding){
+  return crypto
+    .createHash('md5')
+    .update(str)
+    .digest(encoding || 'hex');
+};
+
+/**
+ * Merge object b with object a.
+ *
+ *     var a = { foo: 'bar' }
+ *       , b = { bar: 'baz' };
+ *     
+ *     utils.merge(a, b);
+ *     // => { foo: 'bar', bar: 'baz' }
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object}
+ * @api public
+ */
+
+exports.merge = function(a, b){
+  if (a && b) {
+    for (var key in b) {
+      a[key] = b[key];
+    }
+  }
+  return a;
+};
+
+/**
+ * Escape the given string of `html`.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api public
+ */
+
+exports.escape = function(html){
+  return String(html)
+    .replace(/&(?!\w+;)/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;');
+};
+
+
+/**
+ * Return a unique identifier with the given `len`.
+ *
+ *     utils.uid(10);
+ *     // => "FDaS435D2z"
+ *
+ * @param {Number} len
+ * @return {String}
+ * @api public
+ */
+
+exports.uid = function(len) {
+  var buf = []
+    , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+    , charlen = chars.length;
+
+  for (var i = 0; i < len; ++i) {
+    buf.push(chars[getRandomInt(0, charlen - 1)]);
+  }
+
+  return buf.join('');
+};
+
+/**
+ * Parse the given cookie string into an object.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api public
+ */
+
+exports.parseCookie = function(str){
+  var obj = {}
+    , pairs = str.split(/[;,] */);
+  for (var i = 0, len = pairs.length; i < len; ++i) {
+    var pair = pairs[i]
+      , eqlIndex = pair.indexOf('=')
+      , key = pair.substr(0, eqlIndex).trim().toLowerCase()
+      , val = pair.substr(++eqlIndex, pair.length).trim();
+
+    // quoted values
+    if ('"' == val[0]) val = val.slice(1, -1);
+
+    // only assign once
+    if (undefined == obj[key]) {
+      val = val.replace(/\+/g, ' ');
+      try {
+        obj[key] = decodeURIComponent(val);
+      } catch (err) {
+        if (err instanceof URIError) {
+          obj[key] = val;
+        } else {
+          throw err;
+        }
+      }
+    }
+  }
+  return obj;
+};
+
+/**
+ * Serialize the given object into a cookie string.
+ *
+ *      utils.serializeCookie('name', 'tj', { httpOnly: true })
+ *      // => "name=tj; httpOnly"
+ *
+ * @param {String} name
+ * @param {String} val
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+exports.serializeCookie = function(name, val, obj){
+  var pairs = [name + '=' + encodeURIComponent(val)]
+    , obj = obj || {};
+
+  if (obj.domain) pairs.push('domain=' + obj.domain);
+  if (obj.path) pairs.push('path=' + obj.path);
+  if (obj.expires) pairs.push('expires=' + obj.expires.toUTCString());
+  if (obj.httpOnly) pairs.push('httpOnly');
+  if (obj.secure) pairs.push('secure');
+
+  return pairs.join('; ');
+};
+
+/**
+ * Pause `data` and `end` events on the given `obj`.
+ * Middleware performing async tasks _should_ utilize
+ * this utility (or similar), to re-emit data once
+ * the async operation has completed, otherwise these
+ * events may be lost.
+ *
+ *      var pause = utils.pause(req);
+ *      fs.readFile(path, function(){
+ *         next();
+ *         pause.resume();
+ *      });
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.pause = function(obj){
+  var onData
+    , onEnd
+    , events = [];
+
+  // buffer data
+  obj.on('data', onData = function(data, encoding){
+    events.push(['data', data, encoding]);
+  });
+
+  // buffer end
+  obj.on('end', onEnd = function(data, encoding){
+    events.push(['end', data, encoding]);
+  });
+
+  return {
+    end: function(){
+      obj.removeListener('data', onData);
+      obj.removeListener('end', onEnd);
+    },
+    resume: function(){
+      this.end();
+      for (var i = 0, len = events.length; i < len; ++i) {
+        obj.emit.apply(obj, events[i]);
+      }
+    }
+  };
+};
+
+/**
+ * Check `req` and `res` to see if it has been modified.
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @return {Boolean}
+ * @api public
+ */
+
+exports.modified = function(req, res, headers) {
+  var headers = headers || res._headers || {}
+    , modifiedSince = req.headers['if-modified-since']
+    , lastModified = headers['last-modified']
+    , noneMatch = req.headers['if-none-match']
+    , etag = headers['etag'];
+
+  if (noneMatch) noneMatch = noneMatch.split(/ *, */);
+
+  // check If-None-Match
+  if (noneMatch && etag && ~noneMatch.indexOf(etag)) {
+    return false;
+  }
+
+  // check If-Modified-Since
+  if (modifiedSince && lastModified) {
+    modifiedSince = new Date(modifiedSince);
+    lastModified = new Date(lastModified);
+    // Ignore invalid dates
+    if (!isNaN(modifiedSince.getTime())) {
+      if (lastModified <= modifiedSince) return false;
+    }
+  }
+  
+  return true;
+};
+
+/**
+ * Strip `Content-*` headers from `res`.
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.removeContentHeaders = function(res){
+  Object.keys(res._headers).forEach(function(field){
+    if (0 == field.indexOf('content')) {
+      res.removeHeader(field);
+    }
+  });
+};
+
+/**
+ * Check if `req` is a conditional GET request.
+ *
+ * @param {IncomingMessage} req
+ * @return {Boolean}
+ * @api public
+ */
+
+exports.conditionalGET = function(req) {
+  return req.headers['if-modified-since']
+    || req.headers['if-none-match'];
+};
+
+/**
+ * Respond with 403 "Forbidden".
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.forbidden = function(res) {
+  var body = 'Forbidden';
+  res.setHeader('Content-Type', 'text/plain');
+  res.setHeader('Content-Length', body.length);
+  res.statusCode = 403;
+  res.end(body);
+};
+
+/**
+ * Respond with 401 "Unauthorized".
+ *
+ * @param {ServerResponse} res
+ * @param {String} realm
+ * @api public
+ */
+
+exports.unauthorized = function(res, realm) {
+  res.statusCode = 401;
+  res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
+  res.end('Unauthorized');
+};
+
+/**
+ * Respond with 400 "Bad Request".
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.badRequest = function(res) {
+  res.statusCode = 400;
+  res.end('Bad Request');
+};
+
+/**
+ * Respond with 304 "Not Modified".
+ *
+ * @param {ServerResponse} res
+ * @param {Object} headers
+ * @api public
+ */
+
+exports.notModified = function(res) {
+  exports.removeContentHeaders(res);
+  res.statusCode = 304;
+  res.end();
+};
+
+/**
+ * Return an ETag in the form of `"<size>-<mtime>"`
+ * from the given `stat`.
+ *
+ * @param {Object} stat
+ * @return {String}
+ * @api public
+ */
+
+exports.etag = function(stat) {
+  return '"' + stat.size + '-' + Number(stat.mtime) + '"';
+};
+
+/**
+ * Parse "Range" header `str` relative to the given file `size`.
+ *
+ * @param {Number} size
+ * @param {String} str
+ * @return {Array}
+ * @api public
+ */
+
+exports.parseRange = function(size, str){
+  var valid = true;
+  var arr = str.substr(6).split(',').map(function(range){
+    var range = range.split('-')
+      , start = parseInt(range[0], 10)
+      , end = parseInt(range[1], 10);
+
+    // -500
+    if (isNaN(start)) {
+      start = size - end;
+      end = size - 1;
+    // 500-
+    } else if (isNaN(end)) {
+      end = size - 1;
+    }
+
+    // Invalid
+    if (isNaN(start) || isNaN(end) || start > end) valid = false;
+
+    return { start: start, end: end };
+  });
+  return valid ? arr : undefined;
+};
+
+/**
+ * Parse the given Cache-Control `str`.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api public
+ */
+
+exports.parseCacheControl = function(str){
+  var directives = str.split(',')
+    , obj = {};
+
+  for(var i = 0, len = directives.length; i < len; i++) {
+    var parts = directives[i].split('=')
+      , key = parts.shift().trim()
+      , val = parseInt(parts.shift(), 10);
+
+    obj[key] = isNaN(val) ? true : val;
+  }
+
+  return obj;
+};
+
+
+/**
+ * Convert array-like object to an `Array`.
+ *
+ * node-bench measured "16.5 times faster than Array.prototype.slice.call()"
+ *
+ * @param {Object} obj
+ * @return {Array}
+ * @api public
+ */
+
+var toArray = exports.toArray = function(obj){
+  var len = obj.length
+    , arr = new Array(len);
+  for (var i = 0; i < len; ++i) {
+    arr[i] = obj[i];
+  }
+  return arr;
+};
+
+/**
+ * Retrun a random int, used by `utils.uid()`
+ *
+ * @param {Number} min
+ * @param {Number} max
+ * @return {Number}
+ * @api private
+ */
+
+function getRandomInt(min, max) {
+  return Math.floor(Math.random() * (max - min + 1)) + min;
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.gitignore b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.gitignore
new file mode 100644
index 0000000..b72f74f
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.gitignore
@@ -0,0 +1,4 @@
+/test/tmp
+*.upload
+*.un~
+/node_modules
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore
new file mode 100644
index 0000000..4fbabb3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore
@@ -0,0 +1,4 @@
+/test/tmp/
+*.upload
+*.un~
+*.http
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml
new file mode 100644
index 0000000..f1d0f13
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.4
+  - 0.6
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile
new file mode 100644
index 0000000..8945872
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile
@@ -0,0 +1,14 @@
+SHELL := /bin/bash
+
+test:
+	@./test/run.js
+
+build: npm test
+
+npm:
+	npm install .
+
+clean:
+	rm test/tmp/*
+
+.PHONY: test clean build
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md
new file mode 100644
index 0000000..ca3c00a
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md
@@ -0,0 +1,286 @@
+# Formidable
+
+[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png)](http://travis-ci.org/felixge/node-formidable)
+
+## Purpose
+
+A node.js module for parsing form data, especially file uploads.
+
+## Current status
+
+This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
+and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
+a large variety of clients and is considered production-ready.
+
+## Features
+
+* Fast (~500mb/sec), non-buffering multipart parser
+* Automatically writing file uploads to disk
+* Low memory footprint
+* Graceful error handling
+* Very high test coverage
+
+## Changelog
+
+### v1.0.6
+
+* Do not default to the default to the field name for file uploads where
+  filename="".
+
+### v1.0.5
+
+* Support filename="" in multipart parts
+* Explain unexpected end() errors in parser better
+
+**Note:** Starting with this version, formidable emits 'file' events for empty
+file input fields. Previously those were incorrectly emitted as regular file
+input fields with value = "".
+
+### v1.0.4
+
+* Detect a good default tmp directory regardless of platform. (#88)
+
+### v1.0.3
+
+* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
+* Small performance improvements
+* New test suite and fixture system
+
+### v1.0.2
+
+* Exclude node\_modules folder from git
+* Implement new `'aborted'` event
+* Fix files in example folder to work with recent node versions
+* Make gently a devDependency
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
+
+### v1.0.1
+
+* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
+
+### v1.0.0
+
+* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
+
+This marks the beginning of development on version 2.0 which will include
+several architectural improvements.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
+
+### v0.9.11
+
+* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)
+* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
+
+**Important:** The old property names of the File class will be removed in a
+future release.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
+
+### Older releases
+
+These releases were done before starting to maintain the above Changelog:
+
+* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
+* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
+* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
+* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
+* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
+* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
+* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
+* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
+* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
+* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
+
+## Installation
+
+Via [npm](http://github.com/isaacs/npm):
+
+    npm install formidable@latest
+
+Manually:
+
+    git clone git://github.com/felixge/node-formidable.git formidable
+    vim my.js
+    # var formidable = require('./formidable');
+
+Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.
+
+## Example
+
+Parse an incoming file upload.
+
+    var formidable = require('formidable'),
+        http = require('http'),
+
+        sys = require('sys');
+
+    http.createServer(function(req, res) {
+      if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
+        // parse a file upload
+        var form = new formidable.IncomingForm();
+        form.parse(req, function(err, fields, files) {
+          res.writeHead(200, {'content-type': 'text/plain'});
+          res.write('received upload:\n\n');
+          res.end(sys.inspect({fields: fields, files: files}));
+        });
+        return;
+      }
+
+      // show a file upload form
+      res.writeHead(200, {'content-type': 'text/html'});
+      res.end(
+        '<form action="/upload" enctype="multipart/form-data" method="post">'+
+        '<input type="text" name="title"><br>'+
+        '<input type="file" name="upload" multiple="multiple"><br>'+
+        '<input type="submit" value="Upload">'+
+        '</form>'
+      );
+    }).listen(80);
+
+## API
+
+### formidable.IncomingForm
+
+#### new formidable.IncomingForm()
+
+Creates a new incoming form.
+
+#### incomingForm.encoding = 'utf-8'
+
+The encoding to use for incoming form fields.
+
+#### incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()
+
+The directory for placing file uploads in. You can move them later on using
+`fs.rename()`. The default directory is picked at module load time depending on
+the first existing directory from those listed above.
+
+#### incomingForm.keepExtensions = false
+
+If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`.
+
+#### incomingForm.type
+
+Either 'multipart' or 'urlencoded' depending on the incoming request.
+
+#### incomingForm.maxFieldsSize = 2 * 1024 * 1024
+
+Limits the amount of memory a field (not file) can allocate in bytes.
+If this value is exceeded, an `'error'` event is emitted. The default
+size is 2MB.
+
+#### incomingForm.bytesReceived
+
+The amount of bytes received for this form so far.
+
+#### incomingForm.bytesExpected
+
+The expected number of bytes in this form.
+
+#### incomingForm.parse(request, [cb])
+
+Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:
+
+    incomingForm.parse(req, function(err, fields, files) {
+      // ...
+    });
+
+#### incomingForm.onPart(part)
+
+You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events  processing which would occur otherwise, making you fully responsible for handling the processing.
+
+    incomingForm.onPart = function(part) {
+      part.addListener('data', function() {
+        // ...
+      });
+    }
+
+If you want to use formidable to only handle certain parts for you, you can do so:
+
+    incomingForm.onPart = function(part) {
+      if (!part.filename) {
+        // let formidable handle all non-file parts
+        incomingForm.handlePart(part);
+      }
+    }
+
+Check the code in this method for further inspiration.
+
+#### Event: 'progress' (bytesReceived, bytesExpected)
+
+Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.
+
+#### Event: 'field' (name, value)
+
+Emitted whenever a field / value pair has been received.
+
+#### Event: 'fileBegin' (name, file)
+
+Emitted whenever a new file is detected in the upload stream. Use this even if
+you want to stream the file to somewhere else while buffering the upload on
+the file system.
+
+#### Event: 'file' (name, file)
+
+Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
+
+#### Event: 'error' (err)
+
+Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.
+
+#### Event: 'aborted'
+
+Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).
+
+#### Event: 'end' ()
+
+Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.
+
+### formidable.File
+
+#### file.size = 0
+
+The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.
+
+#### file.path = null
+
+The path this file is being written to. You can modify this in the `'fileBegin'` event in
+case you are unhappy with the way formidable generates a temporary path for your files.
+
+#### file.name = null
+
+The name this file had according to the uploading client.
+
+#### file.type = null
+
+The mime type of this file, according to the uploading client.
+
+#### file.lastModifiedDate = null
+
+A date object (or `null`) containing the time this file was last written to. Mostly
+here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
+
+## License
+
+Formidable is licensed under the MIT license.
+
+## Ports
+
+* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable
+
+## Credits
+
+* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/TODO b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/TODO
new file mode 100644
index 0000000..e1107f2
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/TODO
@@ -0,0 +1,3 @@
+- Better bufferMaxSize handling approach
+- Add tests for JSON parser pull request and merge it
+- Implement QuerystringParser the same way as MultipartParser
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js
new file mode 100644
index 0000000..bff41f1
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js
@@ -0,0 +1,70 @@
+require('../test/common');
+var multipartParser = require('../lib/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    parser = new MultipartParser(),
+    Buffer = require('buffer').Buffer,
+    boundary = '-----------------------------168072824752491622650073',
+    mb = 100,
+    buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+    callbacks =
+      { partBegin: -1,
+        partEnd: -1,
+        headerField: -1,
+        headerValue: -1,
+        partData: -1,
+        end: -1,
+      };
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+  callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+  callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+  callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+  callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+  callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+  callbacks.end++;
+};
+
+var start = +new Date(),
+    nparsed = parser.write(buffer),
+    duration = +new Date - start,
+    mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+  var head =
+        '--'+boundary+'\r\n'
+      + 'content-disposition: form-data; name="field1"\r\n'
+      + '\r\n'
+    , tail = '\r\n--'+boundary+'--\r\n'
+    , buffer = new Buffer(size);
+
+  buffer.write(head, 'ascii', 0);
+  buffer.write(tail, 'ascii', buffer.length - tail.length);
+  return buffer;
+}
+
+process.on('exit', function() {
+  for (var k in callbacks) {
+    assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+  }
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js
new file mode 100644
index 0000000..f6c15a6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js
@@ -0,0 +1,43 @@
+require('../test/common');
+var http = require('http'),
+    util = require('util'),
+    formidable = require('formidable'),
+    server;
+
+server = http.createServer(function(req, res) {
+  if (req.url == '/') {
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/post" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="text" name="data[foo][]"><br>'+
+      '<input type="submit" value="Submit">'+
+      '</form>'
+    );
+  } else if (req.url == '/post') {
+    var form = new formidable.IncomingForm(),
+        fields = [];
+
+    form
+      .on('error', function(err) {
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.end('error:\n\n'+util.inspect(err));
+      })
+      .on('field', function(field, value) {
+        console.log(field, value);
+        fields.push([field, value]);
+      })
+      .on('end', function() {
+        console.log('-> post done');
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.end('received fields:\n\n '+util.inspect(fields));
+      });
+    form.parse(req);
+  } else {
+    res.writeHead(404, {'content-type': 'text/plain'});
+    res.end('404');
+  }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js
new file mode 100644
index 0000000..050cdd9
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js
@@ -0,0 +1,48 @@
+require('../test/common');
+var http = require('http'),
+    util = require('util'),
+    formidable = require('formidable'),
+    server;
+
+server = http.createServer(function(req, res) {
+  if (req.url == '/') {
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/upload" enctype="multipart/form-data" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="file" name="upload" multiple="multiple"><br>'+
+      '<input type="submit" value="Upload">'+
+      '</form>'
+    );
+  } else if (req.url == '/upload') {
+    var form = new formidable.IncomingForm(),
+        files = [],
+        fields = [];
+
+    form.uploadDir = TEST_TMP;
+
+    form
+      .on('field', function(field, value) {
+        console.log(field, value);
+        fields.push([field, value]);
+      })
+      .on('file', function(field, file) {
+        console.log(field, file);
+        files.push([field, file]);
+      })
+      .on('end', function() {
+        console.log('-> upload done');
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.write('received fields:\n\n '+util.inspect(fields));
+        res.write('\n\n');
+        res.end('received files:\n\n '+util.inspect(files));
+      });
+    form.parse(req);
+  } else {
+    res.writeHead(404, {'content-type': 'text/plain'});
+    res.end('404');
+  }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/index.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/index.js
new file mode 100644
index 0000000..be41032
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/index.js
@@ -0,0 +1 @@
+module.exports = require('./lib/formidable');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js
new file mode 100644
index 0000000..6dc8720
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js
@@ -0,0 +1,61 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var util = require('./util'),
+    WriteStream = require('fs').WriteStream,
+    EventEmitter = require('events').EventEmitter;
+
+function File(properties) {
+  EventEmitter.call(this);
+
+  this.size = 0;
+  this.path = null;
+  this.name = null;
+  this.type = null;
+  this.lastModifiedDate = null;
+
+  this._writeStream = null;
+
+  for (var key in properties) {
+    this[key] = properties[key];
+  }
+
+  this._backwardsCompatibility();
+}
+module.exports = File;
+util.inherits(File, EventEmitter);
+
+// @todo Next release: Show error messages when accessing these
+File.prototype._backwardsCompatibility = function() {
+  var self = this;
+  this.__defineGetter__('length', function() {
+    return self.size;
+  });
+  this.__defineGetter__('filename', function() {
+    return self.name;
+  });
+  this.__defineGetter__('mime', function() {
+    return self.type;
+  });
+};
+
+File.prototype.open = function() {
+  this._writeStream = new WriteStream(this.path);
+};
+
+File.prototype.write = function(buffer, cb) {
+  var self = this;
+  this._writeStream.write(buffer, function() {
+    self.lastModifiedDate = new Date();
+    self.size += buffer.length;
+    self.emit('progress', self.size);
+    cb();
+  });
+};
+
+File.prototype.end = function(cb) {
+  var self = this;
+  this._writeStream.end(function() {
+    self.emit('end');
+    cb();
+  });
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js
new file mode 100644
index 0000000..7b1ddaf
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js
@@ -0,0 +1,377 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var fs = require('fs');
+var util = require('./util'),
+    path = require('path'),
+    File = require('./file'),
+    MultipartParser = require('./multipart_parser').MultipartParser,
+    QuerystringParser = require('./querystring_parser').QuerystringParser,
+    StringDecoder = require('string_decoder').StringDecoder,
+    EventEmitter = require('events').EventEmitter;
+
+function IncomingForm() {
+  if (!(this instanceof IncomingForm)) return new IncomingForm;
+  EventEmitter.call(this);
+
+  this.error = null;
+  this.ended = false;
+
+  this.maxFieldsSize = 2 * 1024 * 1024;
+  this.keepExtensions = false;
+  this.uploadDir = IncomingForm.UPLOAD_DIR;
+  this.encoding = 'utf-8';
+  this.headers = null;
+  this.type = null;
+
+  this.bytesReceived = null;
+  this.bytesExpected = null;
+
+  this._parser = null;
+  this._flushing = 0;
+  this._fieldsSize = 0;
+};
+util.inherits(IncomingForm, EventEmitter);
+exports.IncomingForm = IncomingForm;
+
+IncomingForm.UPLOAD_DIR = (function() {
+  var dirs = [process.env.TMP, '/tmp', process.cwd()];
+  for (var i = 0; i < dirs.length; i++) {
+    var dir = dirs[i];
+    var isDirectory = false;
+
+    try {
+      isDirectory = fs.statSync(dir).isDirectory();
+    } catch (e) {}
+
+    if (isDirectory) return dir;
+  }
+})();
+
+IncomingForm.prototype.parse = function(req, cb) {
+  this.pause = function() {
+    try {
+      req.pause();
+    } catch (err) {
+      // the stream was destroyed
+      if (!this.ended) {
+        // before it was completed, crash & burn
+        this._error(err);
+      }
+      return false;
+    }
+    return true;
+  };
+
+  this.resume = function() {
+    try {
+      req.resume();
+    } catch (err) {
+      // the stream was destroyed
+      if (!this.ended) {
+        // before it was completed, crash & burn
+        this._error(err);
+      }
+      return false;
+    }
+
+    return true;
+  };
+
+  this.writeHeaders(req.headers);
+
+  var self = this;
+  req
+    .on('error', function(err) {
+      self._error(err);
+    })
+    .on('aborted', function() {
+      self.emit('aborted');
+    })
+    .on('data', function(buffer) {
+      self.write(buffer);
+    })
+    .on('end', function() {
+      if (self.error) {
+        return;
+      }
+
+      var err = self._parser.end();
+      if (err) {
+        self._error(err);
+      }
+    });
+
+  if (cb) {
+    var fields = {}, files = {};
+    this
+      .on('field', function(name, value) {
+        fields[name] = value;
+      })
+      .on('file', function(name, file) {
+        files[name] = file;
+      })
+      .on('error', function(err) {
+        cb(err, fields, files);
+      })
+      .on('end', function() {
+        cb(null, fields, files);
+      });
+  }
+
+  return this;
+};
+
+IncomingForm.prototype.writeHeaders = function(headers) {
+  this.headers = headers;
+  this._parseContentLength();
+  this._parseContentType();
+};
+
+IncomingForm.prototype.write = function(buffer) {
+  if (!this._parser) {
+    this._error(new Error('unintialized parser'));
+    return;
+  }
+
+  this.bytesReceived += buffer.length;
+  this.emit('progress', this.bytesReceived, this.bytesExpected);
+
+  var bytesParsed = this._parser.write(buffer);
+  if (bytesParsed !== buffer.length) {
+    this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
+  }
+
+  return bytesParsed;
+};
+
+IncomingForm.prototype.pause = function() {
+  // this does nothing, unless overwritten in IncomingForm.parse
+  return false;
+};
+
+IncomingForm.prototype.resume = function() {
+  // this does nothing, unless overwritten in IncomingForm.parse
+  return false;
+};
+
+IncomingForm.prototype.onPart = function(part) {
+  // this method can be overwritten by the user
+  this.handlePart(part);
+};
+
+IncomingForm.prototype.handlePart = function(part) {
+  var self = this;
+
+  if (part.filename === undefined) {
+    var value = ''
+      , decoder = new StringDecoder(this.encoding);
+
+    part.on('data', function(buffer) {
+      self._fieldsSize += buffer.length;
+      if (self._fieldsSize > self.maxFieldsSize) {
+        self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
+        return;
+      }
+      value += decoder.write(buffer);
+    });
+
+    part.on('end', function() {
+      self.emit('field', part.name, value);
+    });
+    return;
+  }
+
+  this._flushing++;
+
+  var file = new File({
+    path: this._uploadPath(part.filename),
+    name: part.filename,
+    type: part.mime,
+  });
+
+  this.emit('fileBegin', part.name, file);
+
+  file.open();
+
+  part.on('data', function(buffer) {
+    self.pause();
+    file.write(buffer, function() {
+      self.resume();
+    });
+  });
+
+  part.on('end', function() {
+    file.end(function() {
+      self._flushing--;
+      self.emit('file', part.name, file);
+      self._maybeEnd();
+    });
+  });
+};
+
+IncomingForm.prototype._parseContentType = function() {
+  if (!this.headers['content-type']) {
+    this._error(new Error('bad content-type header, no content-type'));
+    return;
+  }
+
+  if (this.headers['content-type'].match(/urlencoded/i)) {
+    this._initUrlencoded();
+    return;
+  }
+
+  if (this.headers['content-type'].match(/multipart/i)) {
+    var m;
+    if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
+      this._initMultipart(m[1] || m[2]);
+    } else {
+      this._error(new Error('bad content-type header, no multipart boundary'));
+    }
+    return;
+  }
+
+  this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
+};
+
+IncomingForm.prototype._error = function(err) {
+  if (this.error) {
+    return;
+  }
+
+  this.error = err;
+  this.pause();
+  this.emit('error', err);
+};
+
+IncomingForm.prototype._parseContentLength = function() {
+  if (this.headers['content-length']) {
+    this.bytesReceived = 0;
+    this.bytesExpected = parseInt(this.headers['content-length'], 10);
+  }
+};
+
+IncomingForm.prototype._newParser = function() {
+  return new MultipartParser();
+};
+
+IncomingForm.prototype._initMultipart = function(boundary) {
+  this.type = 'multipart';
+
+  var parser = new MultipartParser(),
+      self = this,
+      headerField,
+      headerValue,
+      part;
+
+  parser.initWithBoundary(boundary);
+
+  parser.onPartBegin = function() {
+    part = new EventEmitter();
+    part.headers = {};
+    part.name = null;
+    part.filename = null;
+    part.mime = null;
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeaderField = function(b, start, end) {
+    headerField += b.toString(self.encoding, start, end);
+  };
+
+  parser.onHeaderValue = function(b, start, end) {
+    headerValue += b.toString(self.encoding, start, end);
+  };
+
+  parser.onHeaderEnd = function() {
+    headerField = headerField.toLowerCase();
+    part.headers[headerField] = headerValue;
+
+    var m;
+    if (headerField == 'content-disposition') {
+      if (m = headerValue.match(/name="([^"]+)"/i)) {
+        part.name = m[1];
+      }
+
+      part.filename = self._fileName(headerValue);
+    } else if (headerField == 'content-type') {
+      part.mime = headerValue;
+    }
+
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeadersEnd = function() {
+    self.onPart(part);
+  };
+
+  parser.onPartData = function(b, start, end) {
+    part.emit('data', b.slice(start, end));
+  };
+
+  parser.onPartEnd = function() {
+    part.emit('end');
+  };
+
+  parser.onEnd = function() {
+    self.ended = true;
+    self._maybeEnd();
+  };
+
+  this._parser = parser;
+};
+
+IncomingForm.prototype._fileName = function(headerValue) {
+  var m = headerValue.match(/filename="(.*?)"($|; )/i)
+  if (!m) return;
+
+  var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
+  filename = filename.replace(/%22/g, '"');
+  filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
+    return String.fromCharCode(code);
+  });
+  return filename;
+};
+
+IncomingForm.prototype._initUrlencoded = function() {
+  this.type = 'urlencoded';
+
+  var parser = new QuerystringParser()
+    , self = this;
+
+  parser.onField = function(key, val) {
+    self.emit('field', key, val);
+  };
+
+  parser.onEnd = function() {
+    self.ended = true;
+    self._maybeEnd();
+  };
+
+  this._parser = parser;
+};
+
+IncomingForm.prototype._uploadPath = function(filename) {
+  var name = '';
+  for (var i = 0; i < 32; i++) {
+    name += Math.floor(Math.random() * 16).toString(16);
+  }
+
+  if (this.keepExtensions) {
+    var ext = path.extname(filename);
+    ext     = ext.replace(/(\.[a-z0-9]+).*/, '$1')
+
+    name += ext;
+  }
+
+  return path.join(this.uploadDir, name);
+};
+
+IncomingForm.prototype._maybeEnd = function() {
+  if (!this.ended || this._flushing) {
+    return;
+  }
+
+  this.emit('end');
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js
new file mode 100644
index 0000000..7a6e3e1
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js
@@ -0,0 +1,3 @@
+var IncomingForm = require('./incoming_form').IncomingForm;
+IncomingForm.IncomingForm = IncomingForm;
+module.exports = IncomingForm;
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js
new file mode 100644
index 0000000..9ca567c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js
@@ -0,0 +1,312 @@
+var Buffer = require('buffer').Buffer,
+    s = 0,
+    S =
+    { PARSER_UNINITIALIZED: s++,
+      START: s++,
+      START_BOUNDARY: s++,
+      HEADER_FIELD_START: s++,
+      HEADER_FIELD: s++,
+      HEADER_VALUE_START: s++,
+      HEADER_VALUE: s++,
+      HEADER_VALUE_ALMOST_DONE: s++,
+      HEADERS_ALMOST_DONE: s++,
+      PART_DATA_START: s++,
+      PART_DATA: s++,
+      PART_END: s++,
+      END: s++,
+    },
+
+    f = 1,
+    F =
+    { PART_BOUNDARY: f,
+      LAST_BOUNDARY: f *= 2,
+    },
+
+    LF = 10,
+    CR = 13,
+    SPACE = 32,
+    HYPHEN = 45,
+    COLON = 58,
+    A = 97,
+    Z = 122,
+
+    lower = function(c) {
+      return c | 0x20;
+    };
+
+for (var s in S) {
+  exports[s] = S[s];
+}
+
+function MultipartParser() {
+  this.boundary = null;
+  this.boundaryChars = null;
+  this.lookbehind = null;
+  this.state = S.PARSER_UNINITIALIZED;
+
+  this.index = null;
+  this.flags = 0;
+};
+exports.MultipartParser = MultipartParser;
+
+MultipartParser.stateToString = function(stateNumber) {
+  for (var state in S) {
+    var number = S[state];
+    if (number === stateNumber) return state;
+  }
+};
+
+MultipartParser.prototype.initWithBoundary = function(str) {
+  this.boundary = new Buffer(str.length+4);
+  this.boundary.write('\r\n--', 'ascii', 0);
+  this.boundary.write(str, 'ascii', 4);
+  this.lookbehind = new Buffer(this.boundary.length+8);
+  this.state = S.START;
+
+  this.boundaryChars = {};
+  for (var i = 0; i < this.boundary.length; i++) {
+    this.boundaryChars[this.boundary[i]] = true;
+  }
+};
+
+MultipartParser.prototype.write = function(buffer) {
+  var self = this,
+      i = 0,
+      len = buffer.length,
+      prevIndex = this.index,
+      index = this.index,
+      state = this.state,
+      flags = this.flags,
+      lookbehind = this.lookbehind,
+      boundary = this.boundary,
+      boundaryChars = this.boundaryChars,
+      boundaryLength = this.boundary.length,
+      boundaryEnd = boundaryLength - 1,
+      bufferLength = buffer.length,
+      c,
+      cl,
+
+      mark = function(name) {
+        self[name+'Mark'] = i;
+      },
+      clear = function(name) {
+        delete self[name+'Mark'];
+      },
+      callback = function(name, buffer, start, end) {
+        if (start !== undefined && start === end) {
+          return;
+        }
+
+        var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+        if (callbackSymbol in self) {
+          self[callbackSymbol](buffer, start, end);
+        }
+      },
+      dataCallback = function(name, clear) {
+        var markSymbol = name+'Mark';
+        if (!(markSymbol in self)) {
+          return;
+        }
+
+        if (!clear) {
+          callback(name, buffer, self[markSymbol], buffer.length);
+          self[markSymbol] = 0;
+        } else {
+          callback(name, buffer, self[markSymbol], i);
+          delete self[markSymbol];
+        }
+      };
+
+  for (i = 0; i < len; i++) {
+    c = buffer[i];
+    switch (state) {
+      case S.PARSER_UNINITIALIZED:
+        return i;
+      case S.START:
+        index = 0;
+        state = S.START_BOUNDARY;
+      case S.START_BOUNDARY:
+        if (index == boundary.length - 2) {
+          if (c != CR) {
+            return i;
+          }
+          index++;
+          break;
+        } else if (index - 1 == boundary.length - 2) {
+          if (c != LF) {
+            return i;
+          }
+          index = 0;
+          callback('partBegin');
+          state = S.HEADER_FIELD_START;
+          break;
+        }
+
+        if (c != boundary[index+2]) {
+          return i;
+        }
+        index++;
+        break;
+      case S.HEADER_FIELD_START:
+        state = S.HEADER_FIELD;
+        mark('headerField');
+        index = 0;
+      case S.HEADER_FIELD:
+        if (c == CR) {
+          clear('headerField');
+          state = S.HEADERS_ALMOST_DONE;
+          break;
+        }
+
+        index++;
+        if (c == HYPHEN) {
+          break;
+        }
+
+        if (c == COLON) {
+          if (index == 1) {
+            // empty header field
+            return i;
+          }
+          dataCallback('headerField', true);
+          state = S.HEADER_VALUE_START;
+          break;
+        }
+
+        cl = lower(c);
+        if (cl < A || cl > Z) {
+          return i;
+        }
+        break;
+      case S.HEADER_VALUE_START:
+        if (c == SPACE) {
+          break;
+        }
+
+        mark('headerValue');
+        state = S.HEADER_VALUE;
+      case S.HEADER_VALUE:
+        if (c == CR) {
+          dataCallback('headerValue', true);
+          callback('headerEnd');
+          state = S.HEADER_VALUE_ALMOST_DONE;
+        }
+        break;
+      case S.HEADER_VALUE_ALMOST_DONE:
+        if (c != LF) {
+          return i;
+        }
+        state = S.HEADER_FIELD_START;
+        break;
+      case S.HEADERS_ALMOST_DONE:
+        if (c != LF) {
+          return i;
+        }
+
+        callback('headersEnd');
+        state = S.PART_DATA_START;
+        break;
+      case S.PART_DATA_START:
+        state = S.PART_DATA
+        mark('partData');
+      case S.PART_DATA:
+        prevIndex = index;
+
+        if (index == 0) {
+          // boyer-moore derrived algorithm to safely skip non-boundary data
+          i += boundaryEnd;
+          while (i < bufferLength && !(buffer[i] in boundaryChars)) {
+            i += boundaryLength;
+          }
+          i -= boundaryEnd;
+          c = buffer[i];
+        }
+
+        if (index < boundary.length) {
+          if (boundary[index] == c) {
+            if (index == 0) {
+              dataCallback('partData', true);
+            }
+            index++;
+          } else {
+            index = 0;
+          }
+        } else if (index == boundary.length) {
+          index++;
+          if (c == CR) {
+            // CR = part boundary
+            flags |= F.PART_BOUNDARY;
+          } else if (c == HYPHEN) {
+            // HYPHEN = end boundary
+            flags |= F.LAST_BOUNDARY;
+          } else {
+            index = 0;
+          }
+        } else if (index - 1 == boundary.length)  {
+          if (flags & F.PART_BOUNDARY) {
+            index = 0;
+            if (c == LF) {
+              // unset the PART_BOUNDARY flag
+              flags &= ~F.PART_BOUNDARY;
+              callback('partEnd');
+              callback('partBegin');
+              state = S.HEADER_FIELD_START;
+              break;
+            }
+          } else if (flags & F.LAST_BOUNDARY) {
+            if (c == HYPHEN) {
+              callback('partEnd');
+              callback('end');
+              state = S.END;
+            } else {
+              index = 0;
+            }
+          } else {
+            index = 0;
+          }
+        }
+
+        if (index > 0) {
+          // when matching a possible boundary, keep a lookbehind reference
+          // in case it turns out to be a false lead
+          lookbehind[index-1] = c;
+        } else if (prevIndex > 0) {
+          // if our boundary turned out to be rubbish, the captured lookbehind
+          // belongs to partData
+          callback('partData', lookbehind, 0, prevIndex);
+          prevIndex = 0;
+          mark('partData');
+
+          // reconsider the current character even so it interrupted the sequence
+          // it could be the beginning of a new sequence
+          i--;
+        }
+
+        break;
+      case S.END:
+        break;
+      default:
+        return i;
+    }
+  }
+
+  dataCallback('headerField');
+  dataCallback('headerValue');
+  dataCallback('partData');
+
+  this.index = index;
+  this.state = state;
+  this.flags = flags;
+
+  return len;
+};
+
+MultipartParser.prototype.end = function() {
+  if (this.state != S.END) {
+    return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
+  }
+};
+
+MultipartParser.prototype.explain = function() {
+  return 'state = ' + MultipartParser.stateToString(this.state);
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js
new file mode 100644
index 0000000..63f109e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js
@@ -0,0 +1,25 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+// This is a buffering parser, not quite as nice as the multipart one.
+// If I find time I'll rewrite this to be fully streaming as well
+var querystring = require('querystring');
+
+function QuerystringParser() {
+  this.buffer = '';
+};
+exports.QuerystringParser = QuerystringParser;
+
+QuerystringParser.prototype.write = function(buffer) {
+  this.buffer += buffer.toString('ascii');
+  return buffer.length;
+};
+
+QuerystringParser.prototype.end = function() {
+  var fields = querystring.parse(this.buffer);
+  for (var field in fields) {
+    this.onField(field, fields[field]);
+  }
+  this.buffer = '';
+
+  this.onEnd();
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js
new file mode 100644
index 0000000..e9493e9
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js
@@ -0,0 +1,6 @@
+// Backwards compatibility ...
+try {
+  module.exports = require('util');
+} catch (e) {
+  module.exports = require('sys');
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js
new file mode 100644
index 0000000..eb432ad
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js
@@ -0,0 +1,19 @@
+var mysql = require('..');
+var path = require('path');
+
+var root = path.join(__dirname, '../');
+exports.dir = {
+  root    : root,
+  lib     : root + '/lib',
+  fixture : root + '/test/fixture',
+  tmp     : root + '/test/tmp',
+};
+
+exports.port = 13532;
+
+exports.formidable = require('..');
+exports.assert     = require('assert');
+
+exports.require = function(lib) {
+  return require(exports.dir.lib + '/' + lib);
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt
new file mode 100644
index 0000000..e7a4785
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt
@@ -0,0 +1 @@
+I am a text file with a funky name!
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt
new file mode 100644
index 0000000..9b6903e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt
@@ -0,0 +1 @@
+I am a plain text file
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http
new file mode 100644
index 0000000..e0dee27
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http
@@ -0,0 +1,13 @@
+POST /upload HTTP/1.1

+Host: localhost:8080

+Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ5CQJVTG

+Content-Length: 1000

+

+------WebKitFormBoundarytyE4wkKlZ5CQJVTG

+Content-Disposition: form-data; name="upload"; filename=""

+Content-Type: text/plain

+

+I am a plain text file
+

+------WebKitFormBoundarytyE4wkKlZ5CQJVTG--

+
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
new file mode 100644
index 0000000..3c9dbe3
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
@@ -0,0 +1,3 @@
+* Opera does not allow submitting this file, it shows a warning to the
+  user that the file could not be found instead. Tested in 9.8, 11.51 on OSX.
+  Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com).
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http
new file mode 100644
index 0000000..4ef3917
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http
@@ -0,0 +1,26 @@
+POST /upload HTTP/1.1

+Host: localhost:8080

+Connection: keep-alive

+Referer: http://localhost:8080/

+Content-Length: 383

+Cache-Control: max-age=0

+Origin: http://localhost:8080

+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1

+Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ5CQJVTG

+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

+Accept-Encoding: gzip,deflate,sdch

+Accept-Language: en-US,en;q=0.8

+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

+Cookie: jqCookieJar_tablesorter=%7B%22showListTable%22%3A%5B%5B5%2C1%5D%2C%5B1%2C0%5D%5D%7D

+

+------WebKitFormBoundarytyE4wkKlZ5CQJVTG

+Content-Disposition: form-data; name="title"

+

+Weird filename

+------WebKitFormBoundarytyE4wkKlZ5CQJVTG

+Content-Disposition: form-data; name="upload"; filename=": \ ? % * | %22 < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: text/plain

+

+I am a text file with a funky name!
+

+------WebKitFormBoundarytyE4wkKlZ5CQJVTG--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http
new file mode 100644
index 0000000..bf49f85
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http
@@ -0,0 +1,24 @@
+POST /upload HTTP/1.1

+Host: localhost:8080

+User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22

+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

+Accept-Language: en-us,en;q=0.5

+Accept-Encoding: gzip,deflate

+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

+Keep-Alive: 115

+Connection: keep-alive

+Referer: http://localhost:8080/

+Content-Type: multipart/form-data; boundary=---------------------------9849436581144108930470211272

+Content-Length: 438

+

+-----------------------------9849436581144108930470211272

+Content-Disposition: form-data; name="title"

+

+Weird filename

+-----------------------------9849436581144108930470211272

+Content-Disposition: form-data; name="upload"; filename=": \ ? % * | " < > . &#9731; ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: text/plain

+

+I am a text file with a funky name!
+

+-----------------------------9849436581144108930470211272--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http
new file mode 100644
index 0000000..ff158a4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http
@@ -0,0 +1,23 @@
+POST /upload HTTP/1.1

+Host: localhost:8080

+Origin: http://localhost:8080

+Content-Length: 383

+User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1

+Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQJZ1gvhvdgfisJPJ

+Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

+Referer: http://localhost:8080/

+Accept-Language: en-us

+Accept-Encoding: gzip, deflate

+Connection: keep-alive

+

+------WebKitFormBoundaryQJZ1gvhvdgfisJPJ

+Content-Disposition: form-data; name="title"

+

+Weird filename

+------WebKitFormBoundaryQJZ1gvhvdgfisJPJ

+Content-Disposition: form-data; name="upload"; filename=": \ ? % * | %22 < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: text/plain

+

+I am a text file with a funky name!
+

+------WebKitFormBoundaryQJZ1gvhvdgfisJPJ--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http
new file mode 100644
index 0000000..f0fc533
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http
@@ -0,0 +1,24 @@
+POST /upload HTTP/1.1

+Host: 192.168.56.1:8080

+Connection: keep-alive

+Referer: http://192.168.56.1:8080/

+Content-Length: 344

+Cache-Control: max-age=0

+Origin: http://192.168.56.1:8080

+User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30

+Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryEvqBNplR3ByrwQPa

+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

+Accept-Encoding: gzip,deflate,sdch

+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

+

+------WebKitFormBoundaryEvqBNplR3ByrwQPa

+Content-Disposition: form-data; name="title"

+

+Weird filename

+------WebKitFormBoundaryEvqBNplR3ByrwQPa

+Content-Disposition: form-data; name="upload"; filename=" ? % * | %22 < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: text/plain

+

+

+------WebKitFormBoundaryEvqBNplR3ByrwQPa--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http
new file mode 100644
index 0000000..2e2c61c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http
@@ -0,0 +1,22 @@
+POST /upload HTTP/1.1

+Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*

+Referer: http://192.168.56.1:8080/

+Accept-Language: de

+User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)

+Content-Type: multipart/form-data; boundary=---------------------------7db1fe232017c

+Accept-Encoding: gzip, deflate

+Host: 192.168.56.1:8080

+Content-Length: 368

+Connection: Keep-Alive

+Cache-Control: no-cache

+

+-----------------------------7db1fe232017c

+Content-Disposition: form-data; name="title"

+

+Weird filename

+-----------------------------7db1fe232017c

+Content-Disposition: form-data; name="upload"; filename=" ? % * | " < > . &#9731; ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: application/octet-stream

+

+

+-----------------------------7db1fe232017c--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http
new file mode 100644
index 0000000..e2b94fa
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http
@@ -0,0 +1,22 @@
+POST /upload HTTP/1.1

+Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*

+Referer: http://192.168.56.1:8080/

+Accept-Language: de

+User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)

+Content-Type: multipart/form-data; boundary=---------------------------7db3a8372017c

+Accept-Encoding: gzip, deflate

+Host: 192.168.56.1:8080

+Content-Length: 368

+Connection: Keep-Alive

+Cache-Control: no-cache

+

+-----------------------------7db3a8372017c

+Content-Disposition: form-data; name="title"

+

+Weird filename

+-----------------------------7db3a8372017c

+Content-Disposition: form-data; name="upload"; filename=" ? % * | " < > . &#9731; ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: application/octet-stream

+

+

+-----------------------------7db3a8372017c--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http
new file mode 100644
index 0000000..6379ac0
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http
@@ -0,0 +1,22 @@
+POST /upload HTTP/1.1

+Host: 192.168.56.1:8080

+Referer: http://192.168.56.1:8080/

+Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

+Accept-Language: en-US

+Origin: http://192.168.56.1:8080

+User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4

+Accept-Encoding: gzip, deflate

+Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykmaWSUbu697WN9TM

+Content-Length: 344

+Connection: keep-alive

+

+------WebKitFormBoundarykmaWSUbu697WN9TM

+Content-Disposition: form-data; name="title"

+

+Weird filename

+------WebKitFormBoundarykmaWSUbu697WN9TM

+Content-Disposition: form-data; name="upload"; filename=" ? % * | %22 < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"

+Content-Type: text/plain

+

+

+------WebKitFormBoundarykmaWSUbu697WN9TM--

diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js
new file mode 100644
index 0000000..0bae449
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js
@@ -0,0 +1,3 @@
+module.exports['generic.http'] = [
+  {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt'},
+];
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js
new file mode 100644
index 0000000..eb76fdc
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js
@@ -0,0 +1,21 @@
+var properFilename = 'funkyfilename.txt';
+
+function expect(filename) {
+  return [
+    {type: 'field', name: 'title', value: 'Weird filename'},
+    {type: 'file', name: 'upload', filename: filename, fixture: properFilename},
+  ];
+};
+
+var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+
+module.exports = {
+  'osx-chrome-13.http'   : expect(webkit),
+  'osx-firefox-3.6.http' : expect(ffOrIe),
+  'osx-safari-5.http'    : expect(webkit),
+  'xp-chrome-12.http'    : expect(webkit),
+  'xp-ie-7.http'         : expect(ffOrIe),
+  'xp-ie-8.http'         : expect(ffOrIe),
+  'xp-safari-5.http'     : expect(webkit),
+};
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js
new file mode 100644
index 0000000..a476169
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js
@@ -0,0 +1,72 @@
+exports['rfc1867'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--\r\n',
+    parts:
+    [ { headers: {
+          'content-disposition': 'form-data; name="field1"',
+        },
+        data: 'Joe Blow\r\nalmost tricked you!',
+      },
+      { headers: {
+          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+          'Content-Type': 'text/plain',
+        },
+        data: '... contents of file1.txt ...\r',
+      }
+    ]
+  };
+
+exports['noTrailing\r\n'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--',
+    parts:
+    [ { headers: {
+          'content-disposition': 'form-data; name="field1"',
+        },
+        data: 'Joe Blow\r\nalmost tricked you!',
+      },
+      { headers: {
+          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+          'Content-Type': 'text/plain',
+        },
+        data: '... contents of file1.txt ...\r',
+      }
+    ]
+  };
+
+exports['emptyHeader'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      ': foo\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--\r\n',
+    expectError: true,
+  };
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js
new file mode 100644
index 0000000..66ad259
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js
@@ -0,0 +1,89 @@
+var hashish = require('hashish');
+var fs = require('fs');
+var findit = require('findit');
+var path = require('path');
+var http = require('http');
+var net = require('net');
+var assert = require('assert');
+
+var common = require('../common');
+var formidable = common.formidable;
+
+var server = http.createServer();
+server.listen(common.port, findFixtures);
+
+function findFixtures() {
+  var fixtures = [];
+  findit
+    .sync(common.dir.fixture + '/js')
+    .forEach(function(jsPath) {
+      if (!/\.js$/.test(jsPath)) return;
+
+      var group = path.basename(jsPath, '.js');
+      hashish.forEach(require(jsPath), function(fixture, name) {
+        fixtures.push({
+          name    : group + '/' + name,
+          fixture : fixture,
+        });
+      });
+    });
+
+  testNext(fixtures);
+}
+
+function testNext(fixtures) {
+  var fixture = fixtures.shift();
+  if (!fixture) return server.close();
+
+  var name    = fixture.name;
+  var fixture = fixture.fixture;
+
+  uploadFixture(name, function(err, parts) {
+    if (err) throw err;
+
+    fixture.forEach(function(expectedPart, i) {
+      var parsedPart = parts[i];
+      assert.equal(parsedPart.type, expectedPart.type);
+      assert.equal(parsedPart.name, expectedPart.name);
+
+      if (parsedPart.type === 'file') {
+        var filename = parsedPart.value.name;
+        assert.equal(filename, expectedPart.filename);
+      }
+    });
+
+    testNext(fixtures);
+  });
+};
+
+function uploadFixture(name, cb) {
+  server.once('request', function(req, res) {
+    var form = new formidable.IncomingForm();
+    form.uploadDir = common.dir.tmp;
+    form.parse(req);
+
+    function callback() {
+      var realCallback = cb;
+      cb = function() {};
+      realCallback.apply(null, arguments);
+    }
+
+    var parts = [];
+    form
+      .on('error', callback)
+      .on('fileBegin', function(name, value) {
+        parts.push({type: 'file', name: name, value: value});
+      })
+      .on('field', function(name, value) {
+        parts.push({type: 'field', name: name, value: value});
+      })
+      .on('end', function() {
+        callback(null, parts);
+      });
+  });
+
+  var socket = net.createConnection(common.port);
+  var file = fs.createReadStream(common.dir.fixture + '/http/' + name);
+
+  file.pipe(socket);
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js
new file mode 100644
index 0000000..2b98598
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js
@@ -0,0 +1,24 @@
+var path = require('path'),
+    fs = require('fs');
+
+try {
+  global.Gently = require('gently');
+} catch (e) {
+  throw new Error('this test suite requires node-gently');
+}
+
+exports.lib = path.join(__dirname, '../../lib');
+
+global.GENTLY = new Gently();
+
+global.assert = require('assert');
+global.TEST_PORT = 13532;
+global.TEST_FIXTURES = path.join(__dirname, '../fixture');
+global.TEST_TMP = path.join(__dirname, '../tmp');
+
+// Stupid new feature in node that complains about gently attaching too many
+// listeners to process 'exit'. This is a workaround until I can think of a
+// better way to deal with this.
+if (process.setMaxListeners) {
+  process.setMaxListeners(10000);
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js
new file mode 100644
index 0000000..75232aa
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js
@@ -0,0 +1,80 @@
+var common = require('../common');
+var CHUNK_LENGTH = 10,
+    multipartParser = require(common.lib + '/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    parser = new MultipartParser(),
+    fixtures = require(TEST_FIXTURES + '/multipart'),
+    Buffer = require('buffer').Buffer;
+
+Object.keys(fixtures).forEach(function(name) {
+  var fixture = fixtures[name],
+      buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')),
+      offset = 0,
+      chunk,
+      nparsed,
+
+      parts = [],
+      part = null,
+      headerField,
+      headerValue,
+      endCalled = '';
+
+  parser.initWithBoundary(fixture.boundary);
+  parser.onPartBegin = function() {
+    part = {headers: {}, data: ''};
+    parts.push(part);
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeaderField = function(b, start, end) {
+    headerField += b.toString('ascii', start, end);
+  };
+
+  parser.onHeaderValue = function(b, start, end) {
+    headerValue += b.toString('ascii', start, end);
+  }
+
+  parser.onHeaderEnd = function() {
+    part.headers[headerField] = headerValue;
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onPartData = function(b, start, end) {
+    var str = b.toString('ascii', start, end);
+    part.data += b.slice(start, end);
+  }
+
+  parser.onEnd = function() {
+    endCalled = true;
+  }
+
+  buffer.write(fixture.raw, 'binary', 0);
+
+  while (offset < buffer.length) {
+    if (offset + CHUNK_LENGTH < buffer.length) {
+      chunk = buffer.slice(offset, offset+CHUNK_LENGTH);
+    } else {
+      chunk = buffer.slice(offset, buffer.length);
+    }
+    offset = offset + CHUNK_LENGTH;
+
+    nparsed = parser.write(chunk);
+    if (nparsed != chunk.length) {
+      if (fixture.expectError) {
+        return;
+      }
+      puts('-- ERROR --');
+      p(chunk.toString('ascii'));
+      throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!');
+    }
+  }
+
+  if (fixture.expectError) {
+    throw new Error('expected parse error did not happen');
+  }
+
+  assert.ok(endCalled);
+  assert.deepEqual(parts, fixture.parts);
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js
new file mode 100644
index 0000000..52ceedb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js
@@ -0,0 +1,104 @@
+var common = require('../common');
+var WriteStreamStub = GENTLY.stub('fs', 'WriteStream');
+
+var File = require(common.lib + '/file'),
+    EventEmitter = require('events').EventEmitter,
+    file,
+    gently;
+
+function test(test) {
+  gently = new Gently();
+  file = new File();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.ok(file instanceof EventEmitter);
+  assert.strictEqual(file.size, 0);
+  assert.strictEqual(file.path, null);
+  assert.strictEqual(file.name, null);
+  assert.strictEqual(file.type, null);
+  assert.strictEqual(file.lastModifiedDate, null);
+
+  assert.strictEqual(file._writeStream, null);
+
+  (function testSetProperties() {
+    var file2 = new File({foo: 'bar'});
+    assert.equal(file2.foo, 'bar');
+  })();
+});
+
+test(function open() {
+  var WRITE_STREAM;
+  file.path = '/foo';
+
+  gently.expect(WriteStreamStub, 'new', function (path) {
+    WRITE_STREAM = this;
+    assert.strictEqual(path, file.path);
+  });
+
+  file.open();
+  assert.strictEqual(file._writeStream, WRITE_STREAM);
+});
+
+test(function write() {
+  var BUFFER = {length: 10},
+      CB_STUB,
+      CB = function() {
+        CB_STUB.apply(this, arguments);
+      };
+
+  file._writeStream = {};
+
+  gently.expect(file._writeStream, 'write', function (buffer, cb) {
+    assert.strictEqual(buffer, BUFFER);
+
+    gently.expect(file, 'emit', function (event, bytesWritten) {
+      assert.ok(file.lastModifiedDate instanceof Date);
+      assert.equal(event, 'progress');
+      assert.equal(bytesWritten, file.size);
+    });
+
+    CB_STUB = gently.expect(function writeCb() {
+      assert.equal(file.size, 10);
+    });
+
+    cb();
+
+    gently.expect(file, 'emit', function (event, bytesWritten) {
+      assert.equal(event, 'progress');
+      assert.equal(bytesWritten, file.size);
+    });
+
+    CB_STUB = gently.expect(function writeCb() {
+      assert.equal(file.size, 20);
+    });
+
+    cb();
+  });
+
+  file.write(BUFFER, CB);
+});
+
+test(function end() {
+  var CB_STUB,
+      CB = function() {
+        CB_STUB.apply(this, arguments);
+      };
+
+  file._writeStream = {};
+
+  gently.expect(file._writeStream, 'end', function (cb) {
+    gently.expect(file, 'emit', function (event) {
+      assert.equal(event, 'end');
+    });
+
+    CB_STUB = gently.expect(function endCb() {
+    });
+
+    cb();
+  });
+
+  file.end(CB);
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js
new file mode 100644
index 0000000..de2bd0c
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js
@@ -0,0 +1,715 @@
+var common = require('../common');
+var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'),
+    QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'),
+    EventEmitterStub = GENTLY.stub('events', 'EventEmitter'),
+    FileStub = GENTLY.stub('./file');
+
+var formidable = require(common.lib + '/index'),
+    IncomingForm = formidable.IncomingForm,
+    events = require('events'),
+    fs = require('fs'),
+    path = require('path'),
+    Buffer = require('buffer').Buffer,
+    fixtures = require(TEST_FIXTURES + '/multipart'),
+    form,
+    gently;
+
+function test(test) {
+  gently = new Gently();
+  gently.expect(EventEmitterStub, 'call');
+  form = new IncomingForm();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.strictEqual(form.error, null);
+  assert.strictEqual(form.ended, false);
+  assert.strictEqual(form.type, null);
+  assert.strictEqual(form.headers, null);
+  assert.strictEqual(form.keepExtensions, false);
+  assert.strictEqual(form.uploadDir, '/tmp');
+  assert.strictEqual(form.encoding, 'utf-8');
+  assert.strictEqual(form.bytesReceived, null);
+  assert.strictEqual(form.bytesExpected, null);
+  assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024);
+  assert.strictEqual(form._parser, null);
+  assert.strictEqual(form._flushing, 0);
+  assert.strictEqual(form._fieldsSize, 0);
+  assert.ok(form instanceof EventEmitterStub);
+  assert.equal(form.constructor.name, 'IncomingForm');
+
+  (function testSimpleConstructor() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = IncomingForm();
+    assert.ok(form instanceof IncomingForm);
+  })();
+
+  (function testSimpleConstructorShortcut() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = formidable();
+    assert.ok(form instanceof IncomingForm);
+  })();
+});
+
+test(function parse() {
+  var REQ = {headers: {}}
+    , emit = {};
+
+  gently.expect(form, 'writeHeaders', function(headers) {
+    assert.strictEqual(headers, REQ.headers);
+  });
+
+  var events = ['error', 'aborted', 'data', 'end'];
+  gently.expect(REQ, 'on', events.length, function(event, fn) {
+    assert.equal(event, events.shift());
+    emit[event] = fn;
+    return this;
+  });
+
+  form.parse(REQ);
+
+  (function testPause() {
+    gently.expect(REQ, 'pause');
+    assert.strictEqual(form.pause(), true);
+  })();
+
+  (function testPauseCriticalException() {
+    form.ended = false;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'pause', function() {
+      throw ERR;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.strictEqual(err, ERR);
+    });
+
+    assert.strictEqual(form.pause(), false);
+  })();
+
+  (function testPauseHarmlessException() {
+    form.ended = true;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'pause', function() {
+      throw ERR;
+    });
+
+    assert.strictEqual(form.pause(), false);
+  })();
+
+  (function testResume() {
+    gently.expect(REQ, 'resume');
+    assert.strictEqual(form.resume(), true);
+  })();
+
+  (function testResumeCriticalException() {
+    form.ended = false;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'resume', function() {
+      throw ERR;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.strictEqual(err, ERR);
+    });
+
+    assert.strictEqual(form.resume(), false);
+  })();
+
+  (function testResumeHarmlessException() {
+    form.ended = true;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'resume', function() {
+      throw ERR;
+    });
+
+    assert.strictEqual(form.resume(), false);
+  })();
+
+  (function testEmitError() {
+    var ERR = new Error('something bad happened');
+    gently.expect(form, '_error',function(err) {
+      assert.strictEqual(err, ERR);
+    });
+    emit.error(ERR);
+  })();
+
+  (function testEmitAborted() {
+    gently.expect(form, 'emit',function(event) {
+      assert.equal(event, 'aborted');
+    });
+
+    emit.aborted();
+  })();
+
+
+  (function testEmitData() {
+    var BUFFER = [1, 2, 3];
+    gently.expect(form, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+    });
+    emit.data(BUFFER);
+  })();
+
+  (function testEmitEnd() {
+    form._parser = {};
+
+    (function testWithError() {
+      var ERR = new Error('haha');
+      gently.expect(form._parser, 'end', function() {
+        return ERR;
+      });
+
+      gently.expect(form, '_error', function(err) {
+        assert.strictEqual(err, ERR);
+      });
+
+      emit.end();
+    })();
+
+    (function testWithoutError() {
+      gently.expect(form._parser, 'end');
+      emit.end();
+    })();
+
+    (function testAfterError() {
+      form.error = true;
+      emit.end();
+    })();
+  })();
+
+  (function testWithCallback() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = new IncomingForm(),
+        REQ = {headers: {}},
+        parseCalled = 0;
+
+    gently.expect(form, 'writeHeaders');
+    gently.expect(REQ, 'on', 4, function() {
+      return this;
+    });
+
+    gently.expect(form, 'on', 4, function(event, fn) {
+      if (event == 'field') {
+        fn('field1', 'foo');
+        fn('field1', 'bar');
+        fn('field2', 'nice');
+      }
+
+      if (event == 'file') {
+        fn('file1', '1');
+        fn('file1', '2');
+        fn('file2', '3');
+      }
+
+      if (event == 'end') {
+        fn();
+      }
+      return this;
+    });
+
+    form.parse(REQ, gently.expect(function parseCbOk(err, fields, files) {
+      assert.deepEqual(fields, {field1: 'bar', field2: 'nice'});
+      assert.deepEqual(files, {file1: '2', file2: '3'});
+    }));
+
+    gently.expect(form, 'writeHeaders');
+    gently.expect(REQ, 'on', 4, function() {
+      return this;
+    });
+
+    var ERR = new Error('test');
+    gently.expect(form, 'on', 3, function(event, fn) {
+      if (event == 'field') {
+        fn('foo', 'bar');
+      }
+
+      if (event == 'error') {
+        fn(ERR);
+        gently.expect(form, 'on');
+      }
+      return this;
+    });
+
+    form.parse(REQ, gently.expect(function parseCbErr(err, fields, files) {
+      assert.strictEqual(err, ERR);
+      assert.deepEqual(fields, {foo: 'bar'});
+    }));
+  })();
+});
+
+test(function pause() {
+  assert.strictEqual(form.pause(), false);
+});
+
+test(function resume() {
+  assert.strictEqual(form.resume(), false);
+});
+
+
+test(function writeHeaders() {
+  var HEADERS = {};
+  gently.expect(form, '_parseContentLength');
+  gently.expect(form, '_parseContentType');
+
+  form.writeHeaders(HEADERS);
+  assert.strictEqual(form.headers, HEADERS);
+});
+
+test(function write() {
+  var parser = {},
+      BUFFER = [1, 2, 3];
+
+  form._parser = parser;
+  form.bytesExpected = 523423;
+
+  (function testBasic() {
+    gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+      assert.equal(event, 'progress');
+      assert.equal(bytesReceived, BUFFER.length);
+      assert.equal(bytesExpected, form.bytesExpected);
+    });
+
+    gently.expect(parser, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+      return buffer.length;
+    });
+
+    assert.equal(form.write(BUFFER), BUFFER.length);
+    assert.equal(form.bytesReceived, BUFFER.length);
+  })();
+
+  (function testParserError() {
+    gently.expect(form, 'emit');
+
+    gently.expect(parser, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+      return buffer.length - 1;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/parser error/i));
+    });
+
+    assert.equal(form.write(BUFFER), BUFFER.length - 1);
+    assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length);
+  })();
+
+  (function testUninitialized() {
+    delete form._parser;
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/unintialized parser/i));
+    });
+    form.write(BUFFER);
+  })();
+});
+
+test(function parseContentType() {
+  var HEADERS = {};
+
+  form.headers = {'content-type': 'application/x-www-form-urlencoded'};
+  gently.expect(form, '_initUrlencoded');
+  form._parseContentType();
+
+  // accept anything that has 'urlencoded' in it
+  form.headers = {'content-type': 'broken-client/urlencoded-stupid'};
+  gently.expect(form, '_initUrlencoded');
+  form._parseContentType();
+
+  var BOUNDARY = '---------------------------57814261102167618332366269';
+  form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY};
+
+  gently.expect(form, '_initMultipart', function(boundary) {
+    assert.equal(boundary, BOUNDARY);
+  });
+  form._parseContentType();
+
+  (function testQuotedBoundary() {
+    form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'};
+
+    gently.expect(form, '_initMultipart', function(boundary) {
+      assert.equal(boundary, BOUNDARY);
+    });
+    form._parseContentType();
+  })();
+
+  (function testNoBoundary() {
+    form.headers = {'content-type': 'multipart/form-data'};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/no multipart boundary/i));
+    });
+    form._parseContentType();
+  })();
+
+  (function testNoContentType() {
+    form.headers = {};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/no content-type/i));
+    });
+    form._parseContentType();
+  })();
+
+  (function testUnknownContentType() {
+    form.headers = {'content-type': 'invalid'};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/unknown content-type/i));
+    });
+    form._parseContentType();
+  })();
+});
+
+test(function parseContentLength() {
+  var HEADERS = {};
+
+  form.headers = {};
+  form._parseContentLength();
+  assert.strictEqual(form.bytesExpected, null);
+
+  form.headers['content-length'] = '8';
+  form._parseContentLength();
+  assert.strictEqual(form.bytesReceived, 0);
+  assert.strictEqual(form.bytesExpected, 8);
+
+  // JS can be evil, lets make sure we are not
+  form.headers['content-length'] = '08';
+  form._parseContentLength();
+  assert.strictEqual(form.bytesExpected, 8);
+});
+
+test(function _initMultipart() {
+  var BOUNDARY = '123',
+      PARSER;
+
+  gently.expect(MultipartParserStub, 'new', function() {
+    PARSER = this;
+  });
+
+  gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) {
+    assert.equal(boundary, BOUNDARY);
+  });
+
+  form._initMultipart(BOUNDARY);
+  assert.equal(form.type, 'multipart');
+  assert.strictEqual(form._parser, PARSER);
+
+  (function testRegularField() {
+    var PART;
+    gently.expect(EventEmitterStub, 'new', function() {
+      PART = this;
+    });
+
+    gently.expect(form, 'onPart', function(part) {
+      assert.strictEqual(part, PART);
+      assert.deepEqual
+        ( part.headers
+        , { 'content-disposition': 'form-data; name="field1"'
+          , 'foo': 'bar'
+          }
+        );
+      assert.equal(part.name, 'field1');
+
+      var strings = ['hello', ' world'];
+      gently.expect(part, 'emit', 2, function(event, b) {
+          assert.equal(event, 'data');
+          assert.equal(b.toString(), strings.shift());
+      });
+
+      gently.expect(part, 'emit', function(event, b) {
+          assert.equal(event, 'end');
+      });
+    });
+
+    PARSER.onPartBegin();
+    PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10);
+    PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24);
+    PARSER.onHeaderEnd();
+    PARSER.onHeaderField(new Buffer('foo'), 0, 3);
+    PARSER.onHeaderValue(new Buffer('bar'), 0, 3);
+    PARSER.onHeaderEnd();
+    PARSER.onHeadersEnd();
+    PARSER.onPartData(new Buffer('hello world'), 0, 5);
+    PARSER.onPartData(new Buffer('hello world'), 5, 11);
+    PARSER.onPartEnd();
+  })();
+
+  (function testFileField() {
+    var PART;
+    gently.expect(EventEmitterStub, 'new', function() {
+      PART = this;
+    });
+
+    gently.expect(form, 'onPart', function(part) {
+      assert.deepEqual
+        ( part.headers
+        , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'
+          , 'content-type': 'text/plain'
+          }
+        );
+      assert.equal(part.name, 'field2');
+      assert.equal(part.filename, 'Sun"et.jpg');
+      assert.equal(part.mime, 'text/plain');
+
+      gently.expect(part, 'emit', function(event, b) {
+        assert.equal(event, 'data');
+        assert.equal(b.toString(), '... contents of file1.txt ...');
+      });
+
+      gently.expect(part, 'emit', function(event, b) {
+          assert.equal(event, 'end');
+      });
+    });
+
+    PARSER.onPartBegin();
+    PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85);
+    PARSER.onHeaderEnd();
+    PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12);
+    PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10);
+    PARSER.onHeaderEnd();
+    PARSER.onHeadersEnd();
+    PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29);
+    PARSER.onPartEnd();
+  })();
+
+  (function testEnd() {
+    gently.expect(form, '_maybeEnd');
+    PARSER.onEnd();
+    assert.ok(form.ended);
+  })();
+});
+
+test(function _fileName() {
+  // TODO
+  return;
+});
+
+test(function _initUrlencoded() {
+  var PARSER;
+
+  gently.expect(QuerystringParserStub, 'new', function() {
+    PARSER = this;
+  });
+
+  form._initUrlencoded();
+  assert.equal(form.type, 'urlencoded');
+  assert.strictEqual(form._parser, PARSER);
+
+  (function testOnField() {
+    var KEY = 'KEY', VAL = 'VAL';
+    gently.expect(form, 'emit', function(field, key, val) {
+      assert.equal(field, 'field');
+      assert.equal(key, KEY);
+      assert.equal(val, VAL);
+    });
+
+    PARSER.onField(KEY, VAL);
+  })();
+
+  (function testOnEnd() {
+    gently.expect(form, '_maybeEnd');
+
+    PARSER.onEnd();
+    assert.equal(form.ended, true);
+  })();
+});
+
+test(function _error() {
+  var ERR = new Error('bla');
+
+  gently.expect(form, 'pause');
+  gently.expect(form, 'emit', function(event, err) {
+    assert.equal(event, 'error');
+    assert.strictEqual(err, ERR);
+  });
+
+  form._error(ERR);
+  assert.strictEqual(form.error, ERR);
+
+  // make sure _error only does its thing once
+  form._error(ERR);
+});
+
+test(function onPart() {
+  var PART = {};
+  gently.expect(form, 'handlePart', function(part) {
+    assert.strictEqual(part, PART);
+  });
+
+  form.onPart(PART);
+});
+
+test(function handlePart() {
+  (function testUtf8Field() {
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field';
+
+    gently.expect(form, 'emit', function(event, field, value) {
+      assert.equal(event, 'field');
+      assert.equal(field, 'my_field');
+      assert.equal(value, 'hello world: €');
+    });
+
+    form.handlePart(PART);
+    PART.emit('data', new Buffer('hello'));
+    PART.emit('data', new Buffer(' world: '));
+    PART.emit('data', new Buffer([0xE2]));
+    PART.emit('data', new Buffer([0x82, 0xAC]));
+    PART.emit('end');
+  })();
+
+  (function testBinaryField() {
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field2';
+
+    gently.expect(form, 'emit', function(event, field, value) {
+      assert.equal(event, 'field');
+      assert.equal(field, 'my_field2');
+      assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary'));
+    });
+
+    form.encoding = 'binary';
+    form.handlePart(PART);
+    PART.emit('data', new Buffer('hello'));
+    PART.emit('data', new Buffer(' world: '));
+    PART.emit('data', new Buffer([0xE2]));
+    PART.emit('data', new Buffer([0x82, 0xAC]));
+    PART.emit('end');
+  })();
+
+  (function testFieldSize() {
+    form.maxFieldsSize = 8;
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field';
+
+    gently.expect(form, '_error', function(err) {
+      assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data');
+    });
+
+    form.handlePart(PART);
+    form._fieldsSize = 1;
+    PART.emit('data', new Buffer(7));
+    PART.emit('data', new Buffer(1));
+  })();
+
+  (function testFilePart() {
+    var PART = new events.EventEmitter(),
+        FILE = new events.EventEmitter(),
+        PATH = '/foo/bar';
+
+    PART.name = 'my_file';
+    PART.filename = 'sweet.txt';
+    PART.mime = 'sweet.txt';
+
+    gently.expect(form, '_uploadPath', function(filename) {
+      assert.equal(filename, PART.filename);
+      return PATH;
+    });
+
+    gently.expect(FileStub, 'new', function(properties) {
+      assert.equal(properties.path, PATH);
+      assert.equal(properties.name, PART.filename);
+      assert.equal(properties.type, PART.mime);
+      FILE = this;
+
+      gently.expect(form, 'emit', function (event, field, file) {
+        assert.equal(event, 'fileBegin');
+        assert.strictEqual(field, PART.name);
+        assert.strictEqual(file, FILE);
+      });
+
+      gently.expect(FILE, 'open');
+    });
+
+    form.handlePart(PART);
+    assert.equal(form._flushing, 1);
+
+    var BUFFER;
+    gently.expect(form, 'pause');
+    gently.expect(FILE, 'write', function(buffer, cb) {
+      assert.strictEqual(buffer, BUFFER);
+      gently.expect(form, 'resume');
+      // @todo handle cb(new Err)
+      cb();
+    });
+
+    PART.emit('data', BUFFER = new Buffer('test'));
+
+    gently.expect(FILE, 'end', function(cb) {
+      gently.expect(form, 'emit', function(event, field, file) {
+        assert.equal(event, 'file');
+        assert.strictEqual(file, FILE);
+      });
+
+      gently.expect(form, '_maybeEnd');
+
+      cb();
+      assert.equal(form._flushing, 0);
+    });
+
+    PART.emit('end');
+  })();
+});
+
+test(function _uploadPath() {
+  (function testUniqueId() {
+    var UUID_A, UUID_B;
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+      assert.equal(uploadDir, form.uploadDir);
+      UUID_A = uuid;
+    });
+    form._uploadPath();
+
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+      UUID_B = uuid;
+    });
+    form._uploadPath();
+
+    assert.notEqual(UUID_A, UUID_B);
+  })();
+
+  (function testFileExtension() {
+    form.keepExtensions = true;
+    var FILENAME = 'foo.jpg',
+        EXT = '.bar';
+
+    gently.expect(GENTLY.hijacked.path, 'extname', function(filename) {
+      assert.equal(filename, FILENAME);
+      gently.restore(path, 'extname');
+
+      return EXT;
+    });
+
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) {
+      assert.equal(path.extname(name), EXT);
+    });
+    form._uploadPath(FILENAME);
+  })();
+});
+
+test(function _maybeEnd() {
+  gently.expect(form, 'emit', 0);
+  form._maybeEnd();
+
+  form.ended = true;
+  form._flushing = 1;
+  form._maybeEnd();
+
+  gently.expect(form, 'emit', function(event) {
+    assert.equal(event, 'end');
+  });
+
+  form.ended = true;
+  form._flushing = 0;
+  form._maybeEnd();
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js
new file mode 100644
index 0000000..d8dc968
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js
@@ -0,0 +1,50 @@
+var common = require('../common');
+var multipartParser = require(common.lib + '/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    events = require('events'),
+    Buffer = require('buffer').Buffer,
+    parser;
+
+function test(test) {
+  parser = new MultipartParser();
+  test();
+}
+
+test(function constructor() {
+  assert.equal(parser.boundary, null);
+  assert.equal(parser.state, 0);
+  assert.equal(parser.flags, 0);
+  assert.equal(parser.boundaryChars, null);
+  assert.equal(parser.index, null);
+  assert.equal(parser.lookbehind, null);
+  assert.equal(parser.constructor.name, 'MultipartParser');
+});
+
+test(function initWithBoundary() {
+  var boundary = 'abc';
+  parser.initWithBoundary(boundary);
+  assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]);
+  assert.equal(parser.state, multipartParser.START);
+
+  assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true});
+});
+
+test(function parserError() {
+  var boundary = 'abc',
+      buffer = new Buffer(5);
+
+  parser.initWithBoundary(boundary);
+  buffer.write('--ad', 'ascii', 0);
+  assert.equal(parser.write(buffer), 3);
+});
+
+test(function end() {
+  (function testError() {
+    assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain());
+  })();
+
+  (function testRegular() {
+    parser.state = multipartParser.END;
+    assert.strictEqual(parser.end(), undefined);
+  })();
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js
new file mode 100644
index 0000000..54d3e2d
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js
@@ -0,0 +1,45 @@
+var common = require('../common');
+var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser,
+    Buffer = require('buffer').Buffer,
+    gently,
+    parser;
+
+function test(test) {
+  gently = new Gently();
+  parser = new QuerystringParser();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.equal(parser.buffer, '');
+  assert.equal(parser.constructor.name, 'QuerystringParser');
+});
+
+test(function write() {
+  var a = new Buffer('a=1');
+  assert.equal(parser.write(a), a.length);
+
+  var b = new Buffer('&b=2');
+  parser.write(b);
+  assert.equal(parser.buffer, a + b);
+});
+
+test(function end() {
+  var FIELDS = {a: ['b', {c: 'd'}], e: 'f'};
+
+  gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) {
+    assert.equal(str, parser.buffer);
+    return FIELDS;
+  });
+
+  gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) {
+    assert.deepEqual(FIELDS[key], val);
+  });
+
+  gently.expect(parser, 'onEnd');
+
+  parser.buffer = 'my buffer';
+  parser.end();
+  assert.equal(parser.buffer, '');
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js
new file mode 100644
index 0000000..fcfdb94
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js
@@ -0,0 +1,72 @@
+var common = require('../common');
+var BOUNDARY = '---------------------------10102754414578508781458777923',
+    FIXTURE = TEST_FIXTURES+'/multi_video.upload',
+    fs = require('fs'),
+    util = require(common.lib + '/util'),
+    http = require('http'),
+    formidable = require(common.lib + '/index'),
+    server = http.createServer();
+
+server.on('request', function(req, res) {
+  var form = new formidable.IncomingForm(),
+      uploads = {};
+
+  form.uploadDir = TEST_TMP;
+  form.parse(req);
+
+  form
+    .on('fileBegin', function(field, file) {
+      assert.equal(field, 'upload');
+
+      var tracker = {file: file, progress: [], ended: false};
+      uploads[file.filename] = tracker;
+      file
+        .on('progress', function(bytesReceived) {
+          tracker.progress.push(bytesReceived);
+          assert.equal(bytesReceived, file.length);
+        })
+        .on('end', function() {
+          tracker.ended = true;
+        });
+    })
+    .on('field', function(field, value) {
+      assert.equal(field, 'title');
+      assert.equal(value, '');
+    })
+    .on('file', function(field, file) {
+      assert.equal(field, 'upload');
+      assert.strictEqual(uploads[file.filename].file, file);
+    })
+    .on('end', function() {
+      assert.ok(uploads['shortest_video.flv']);
+      assert.ok(uploads['shortest_video.flv'].ended);
+      assert.ok(uploads['shortest_video.flv'].progress.length > 3);
+      assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.length);
+      assert.ok(uploads['shortest_video.mp4']);
+      assert.ok(uploads['shortest_video.mp4'].ended);
+      assert.ok(uploads['shortest_video.mp4'].progress.length > 3);
+
+      server.close();
+      res.writeHead(200);
+      res.end('good');
+    });
+});
+
+server.listen(TEST_PORT, function() {
+  var client = http.createClient(TEST_PORT),
+      stat = fs.statSync(FIXTURE),
+      headers = {
+        'content-type': 'multipart/form-data; boundary='+BOUNDARY,
+        'content-length': stat.size,
+      }
+      request = client.request('POST', '/', headers),
+      fixture = new fs.ReadStream(FIXTURE);
+
+  fixture
+    .on('data', function(b) {
+      request.write(b);
+    })
+    .on('end', function() {
+      request.end();
+    });
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js
new file mode 100755
index 0000000..50b2361
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('urun')(__dirname)
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js
new file mode 100644
index 0000000..bcf61d7
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js
@@ -0,0 +1,63 @@
+var common       = require('../common');
+var test         = require('utest');
+var assert       = common.assert;
+var IncomingForm = common.require('incoming_form').IncomingForm;
+var path         = require('path');
+
+var from;
+test('IncomingForm', {
+  before: function() {
+    form = new IncomingForm();
+  },
+
+  '#_fileName with regular characters': function() {
+    var filename = 'foo.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'foo.txt');
+  },
+
+  '#_fileName with unescaped quote': function() {
+    var filename = 'my".txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+  },
+
+  '#_fileName with escaped quote': function() {
+    var filename = 'my%22.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+  },
+
+  '#_fileName with bad quote and additional sub-header': function() {
+    var filename = 'my".txt';
+    var header = makeHeader(filename) + '; foo="bar"';
+    assert.equal(form._fileName(header), filename);
+  },
+
+  '#_fileName with semicolon': function() {
+    var filename = 'my;.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my;.txt');
+  },
+
+  '#_fileName with utf8 character': function() {
+    var filename = 'my&#9731;.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt');
+  },
+
+  '#_uploadPath strips harmful characters from extension when keepExtensions': function() {
+    form.keepExtensions = true;
+
+    var ext = path.extname(form._uploadPath('fine.jpg?foo=bar'));
+    assert.equal(ext, '.jpg');
+
+    var ext = path.extname(form._uploadPath('fine?foo=bar'));
+    assert.equal(ext, '');
+
+    var ext = path.extname(form._uploadPath('super.cr2+dsad'));
+    assert.equal(ext, '.cr2');
+
+    var ext = path.extname(form._uploadPath('super.bar'));
+    assert.equal(ext, '.bar');
+  },
+});
+
+function makeHeader(filename) {
+  return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"';
+}
diff --git a/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js
new file mode 100644
index 0000000..9f1cef8
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js
@@ -0,0 +1,47 @@
+var http = require('http');
+var fs = require('fs');
+var connections = 0;
+
+var server = http.createServer(function(req, res) {
+  var socket = req.socket;
+  console.log('Request: %s %s -> %s', req.method, req.url, socket.filename);
+
+  req.on('end', function() {
+    if (req.url !== '/') {
+      res.end(JSON.stringify({
+        method: req.method,
+        url: req.url,
+        filename: socket.filename,
+      }));
+      return;
+    }
+
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/upload" enctype="multipart/form-data" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="file" name="upload" multiple="multiple"><br>'+
+      '<input type="submit" value="Upload">'+
+      '</form>'
+    );
+  });
+});
+
+server.on('connection', function(socket) {
+  connections++;
+
+  socket.id = connections;
+  socket.filename = 'connection-' + socket.id + '.http';
+  socket.file = fs.createWriteStream(socket.filename);
+  socket.pipe(socket.file);
+
+  console.log('--> %s', socket.filename);
+  socket.on('close', function() {
+    console.log('<-- %s', socket.filename);
+  });
+});
+
+var port = process.env.PORT || 8080;
+server.listen(port, function() {
+  console.log('Recording connections on port %s', port);
+});
diff --git a/weinre.server/node_modules/express/node_modules/connect/test.js b/weinre.server/node_modules/express/node_modules/connect/test.js
new file mode 100644
index 0000000..a1e1d55
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/connect/test.js
@@ -0,0 +1,52 @@
+
+var connect = require('./')
+  , http = require('http')
+  , RedisStore = require('connect-redis')(connect);
+
+var app = connect();
+app.use(connect.cookieParser('fucj'));
+app.use(connect.session({store:new RedisStore}));
+app.use(function(req, res, next){
+  req.session.views = (req.session.views || 0) + 1;
+  res.writeHead(200, {"Content-Type": "text/plain"});
+  res.end("You've viewed this page "+req.session.views+" times.");
+})
+
+http.createServer(app).listen(3000);
+
+
+// var set = RedisStore.prototype.set;
+// 
+// function slow(sid){
+//   console.log('%s saving', sid);
+//   var args = arguments;
+//   setTimeout(function(self){
+//     console.log('%s saved', sid);
+//     set.apply(self, args);
+//   }, 2000, this);
+// };
+// 
+// http.createServer(connect()
+//   .use(connect.logger('dev'))
+//   .use(connect.cookieParser('keyboard cat'))
+//   .use(connect.session({ store: new RedisStore }))
+//   .use(function(req, res, next){
+//     var sess = req.session;
+//     switch (req.url) {
+//       case '/foo.js':
+//         console.log('%s foo.js sid', sess.id);
+//         RedisStore.prototype.set = set;
+//         res.end('data');
+//         break;
+//       default:
+//         console.log('%s html sid', sess.id);
+//         RedisStore.prototype.set = slow;
+//         res.setHeader('Content-Type', 'html');
+//         res.write('<html><head><script src="/foo.js"></script></head><body>');
+//         setTimeout(function(){
+//           res.end('</body></html>');
+//         }, 1000);
+//     }
+//   })).listen(3000);
+// 
+// console.log('port 3000');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/mime/LICENSE b/weinre.server/node_modules/express/node_modules/mime/LICENSE
new file mode 100644
index 0000000..451fc45
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/weinre.server/node_modules/express/node_modules/mime/README.md b/weinre.server/node_modules/express/node_modules/mime/README.md
new file mode 100644
index 0000000..a157de1
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/README.md
@@ -0,0 +1,50 @@
+# mime
+
+Support for mapping between file extensions and MIME types.  This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions).  It is also trivially easy to add your own types and extensions, should you need to do that.
+
+## Install
+
+Install with [npm](http://github.com/isaacs/npm):
+
+    npm install mime
+
+## API - Queries
+
+### mime.lookup(path)
+Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so:
+
+    var mime = require('mime');
+
+    mime.lookup('/path/to/file.txt');         // => 'text/plain'
+    mime.lookup('file.txt');                  // => 'text/plain'
+    mime.lookup('.txt');                      // => 'text/plain'
+    mime.lookup('htm');                       // => 'text/html'
+
+### mime.extension(type) - lookup the default extension for type
+
+    mime.extension('text/html');                 // => 'html'
+    mime.extension('application/octet-stream');  // => 'bin'
+
+### mime.charsets.lookup() - map mime-type to charset
+
+    mime.charsets.lookup('text/plain');        // => 'UTF-8'
+
+(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)
+
+## API - Customizing
+
+The following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types).
+### mime.define() - Add custom mime/extension mappings
+
+    mime.define({
+        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
+        'application/x-my-type': ['x-mt', 'x-mtt'],
+        // etc ...
+    });
+
+    mime.lookup('x-sft');                 // => 'text/x-some-format'
+    mime.extension('text/x-some-format'); // => 'x-sf'
+
+### mime.load(filepath) - Load mappings from an Apache ".types" format file
+
+    mime.load('./my_project.types');
diff --git a/weinre.server/node_modules/express/node_modules/mime/mime.js b/weinre.server/node_modules/express/node_modules/mime/mime.js
new file mode 100644
index 0000000..5fac753
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/mime.js
@@ -0,0 +1,92 @@
+var path = require('path'),
+    fs = require('fs');
+
+var mime = module.exports = {
+  /** Map of extension to mime type */
+  types: {},
+
+  /** Map of mime type to extension */
+  extensions :{},
+
+  /**
+   * Define mimetype -> extension mappings.  Each key is a mime-type that maps
+   * to an array of extensions associated with the type.  The first extension is
+   * used as the default extension for the type.
+   *
+   * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
+   *
+   * @param map (Object) type definitions
+   */
+  define: function(map) {
+    for (var type in map) {
+      var exts = map[type];
+
+      for (var i = 0; i < exts.length; i++) {
+        mime.types[exts[i]] = type;
+      }
+
+      // Default extension is the first one we encounter
+      if (!mime.extensions[type]) {
+        mime.extensions[type] = exts[0];
+      }
+    }
+  },
+
+  /**
+   * Load an Apache2-style ".types" file
+   *
+   * This may be called multiple times (it's expected).  Where files declare
+   * overlapping types/extensions, the last file wins.
+   *
+   * @param file (String) path of file to load.
+   */
+  load: function(file) {
+    // Read file and split into lines
+    var map = {},
+        content = fs.readFileSync(file, 'ascii'),
+        lines = content.split(/[\r\n]+/);
+
+    lines.forEach(function(line, lineno) {
+      // Clean up whitespace/comments, and split into fields
+      var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
+      map[fields.shift()] = fields;
+    });
+
+    mime.define(map);
+  },
+
+  /**
+   * Lookup a mime type based on extension
+   */
+  lookup: function(path, fallback) {
+    var ext = path.replace(/.*[\.\/]/, '').toLowerCase();
+    return mime.types[ext] || fallback || mime.default_type;
+  },
+
+  /**
+   * Return file extension associated with a mime type
+   */
+  extension: function(mimeType) {
+    return mime.extensions[mimeType];
+  },
+
+  /**
+   * Lookup a charset based on mime type.
+   */
+  charsets: {
+    lookup: function (mimeType, fallback) {
+      // Assume text types are utf8.  Modify mime logic as needed.
+      return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
+    }
+  }
+};
+
+// Load our local copy of
+// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+mime.load(path.join(__dirname, 'types/mime.types'));
+
+// Overlay enhancements submitted by the node.js community
+mime.load(path.join(__dirname, 'types/node.types'));
+
+// Set the default type
+mime.default_type = mime.types.bin;
diff --git a/weinre.server/node_modules/express/node_modules/mime/test.js b/weinre.server/node_modules/express/node_modules/mime/test.js
new file mode 100644
index 0000000..b904895
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/test.js
@@ -0,0 +1,79 @@
+/**
+ * Requires the async_testing module
+ *
+ * Usage: node test.js
+ */
+var mime = require('./mime');
+exports["test mime lookup"] = function(test) {
+  // easy
+  test.equal('text/plain', mime.lookup('text.txt'));
+
+  // hidden file or multiple periods
+  test.equal('text/plain', mime.lookup('.text.txt'));
+
+  // just an extension
+  test.equal('text/plain', mime.lookup('.txt'));
+
+  // just an extension without a dot
+  test.equal('text/plain', mime.lookup('txt'));
+
+  // default
+  test.equal('application/octet-stream', mime.lookup('text.nope'));
+
+  // fallback
+  test.equal('fallback', mime.lookup('text.fallback', 'fallback'));
+
+  test.finish();
+};
+
+exports["test extension lookup"] = function(test) {
+  // easy
+  test.equal('txt', mime.extension(mime.types.text));
+  test.equal('html', mime.extension(mime.types.htm));
+  test.equal('bin', mime.extension('application/octet-stream'));
+
+  test.finish();
+};
+
+exports["test mime lookup uppercase"] = function(test) {
+  // easy
+  test.equal('text/plain', mime.lookup('TEXT.TXT'));
+
+  // just an extension
+  test.equal('text/plain', mime.lookup('.TXT'));
+
+  // just an extension without a dot
+  test.equal('text/plain', mime.lookup('TXT'));
+
+  // default
+  test.equal('application/octet-stream', mime.lookup('TEXT.NOPE'));
+
+  // fallback
+  test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback'));
+
+  test.finish();
+};
+
+exports["test custom types"] = function(test) {
+  test.equal('application/octet-stream', mime.lookup('file.buffer'));
+  test.equal('audio/mp4', mime.lookup('file.m4a'));
+
+  test.finish();
+};
+
+exports["test charset lookup"] = function(test) {
+  // easy
+  test.equal('UTF-8', mime.charsets.lookup('text/plain'));
+
+  // none
+  test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined');
+
+  // fallback
+  test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
+
+  test.finish();
+};
+
+if (module == require.main) {
+  require('async_testing').run(__filename, process.ARGV);
+}
diff --git a/weinre.server/node_modules/express/node_modules/mime/types/mime.types b/weinre.server/node_modules/express/node_modules/mime/types/mime.types
new file mode 100644
index 0000000..6a90929
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/types/mime.types
@@ -0,0 +1,1479 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types.  File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at <http://www.iana.org/assignments/media-types/>.
+#
+# MIME type (lowercased)			Extensions
+# ============================================	==========
+# application/1d-interleaved-parityfec
+# application/3gpp-ims+xml
+# application/activemessage
+application/andrew-inset			ez
+# application/applefile
+application/applixware				aw
+application/atom+xml				atom
+application/atomcat+xml				atomcat
+# application/atomicmail
+application/atomsvc+xml				atomsvc
+# application/auth-policy+xml
+# application/batch-smtp
+# application/beep+xml
+# application/cals-1840
+application/ccxml+xml				ccxml
+application/cdmi-capability			cdmia
+application/cdmi-container			cdmic
+application/cdmi-domain				cdmid
+application/cdmi-object				cdmio
+application/cdmi-queue				cdmiq
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cnrp+xml
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csta+xml
+# application/cstadata+xml
+application/cu-seeme				cu
+# application/cybercash
+application/davmount+xml			davmount
+# application/dca-rft
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dns
+# application/dskpp+xml
+application/dssc+der				dssc
+application/dssc+xml				xdssc
+# application/dvcs
+application/ecmascript				ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+application/emma+xml				emma
+# application/epp+xml
+application/epub+zip				epub
+# application/eshop
+# application/example
+application/exi					exi
+# application/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr				pfr
+# application/framework-attributes+xml
+# application/h224
+# application/held+xml
+# application/http
+application/hyperstudio				stk
+# application/ibe-key-request+xml
+# application/ibe-pkg-reply+xml
+# application/ibe-pp-data
+# application/iges
+# application/im-iscomposing+xml
+# application/index
+# application/index.cmd
+# application/index.obj
+# application/index.response
+# application/index.vnd
+# application/iotp
+application/ipfix				ipfix
+# application/ipp
+# application/isup
+application/java-archive			jar
+application/java-serialized-object		ser
+application/java-vm				class
+application/javascript				js
+application/json				json
+# application/kpml-request+xml
+# application/kpml-response+xml
+application/lost+xml				lostxml
+application/mac-binhex40			hqx
+application/mac-compactpro			cpt
+# application/macwriteii
+application/mads+xml				mads
+application/marc				mrc
+application/marcxml+xml				mrcx
+application/mathematica				ma nb mb
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+application/mathml+xml				mathml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-user-service-description+xml
+application/mbox				mbox
+# application/media_control+xml
+application/mediaservercontrol+xml		mscml
+application/metalink4+xml			meta4
+application/mets+xml				mets
+# application/mikey
+application/mods+xml				mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21				m21 mp21
+application/mp4					mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword				doc dot
+application/mxf					mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream	bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy
+application/oda					oda
+application/oebps-package+xml			opf
+application/ogg					ogx
+application/onenote				onetoc onetoc2 onetmp onepkg
+# application/parityfec
+application/patch-ops-error+xml			xer
+application/pdf					pdf
+application/pgp-encrypted			pgp
+# application/pgp-keys
+application/pgp-signature			asc sig
+application/pics-rules				prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10				p10
+application/pkcs7-mime				p7m p7c
+application/pkcs7-signature			p7s
+application/pkcs8				p8
+application/pkix-attr-cert			ac
+application/pkix-cert				cer
+application/pkix-crl				crl
+application/pkix-pkipath			pkipath
+application/pkixcmp				pki
+application/pls+xml				pls
+# application/poc-settings+xml
+application/postscript				ai eps ps
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww				cww
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml				pskcxml
+# application/qsig
+application/rdf+xml				rdf
+application/reginfo+xml				rif
+application/relax-ng-compact-syntax		rnc
+# application/remote-printing
+application/resource-lists+xml			rl
+application/resource-lists-diff+xml		rld
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml			rs
+application/rsd+xml				rsd
+application/rss+xml				rss
+application/rtf					rtf
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml				sbml
+application/scvp-cv-request			scq
+application/scvp-cv-response			scs
+application/scvp-vp-request			spq
+application/scvp-vp-response			spp
+application/sdp					sdp
+# application/set-payment
+application/set-payment-initiation		setpay
+# application/set-registration
+application/set-registration-initiation		setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml				shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml				smi smil
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query			rq
+application/sparql-results+xml			srx
+# application/spirits-event+xml
+application/srgs				gram
+application/srgs+xml				grxml
+application/sru+xml				sru
+application/ssml+xml				ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml				tei teicorpus
+application/thraud+xml				tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data			tsd
+# application/tve-trigger
+# application/ulpfec
+# application/vemmi
+# application/vividence.scriptfile
+# application/vnd.3gpp.bsf+xml
+application/vnd.3gpp.pic-bw-large		plb
+application/vnd.3gpp.pic-bw-small		psb
+application/vnd.3gpp.pic-bw-var			pvb
+# application/vnd.3gpp.sms
+# application/vnd.3gpp2.bcmcsinfo+xml
+# application/vnd.3gpp2.sms
+application/vnd.3gpp2.tcap			tcap
+application/vnd.3m.post-it-notes		pwn
+application/vnd.accpac.simply.aso		aso
+application/vnd.accpac.simply.imp		imp
+application/vnd.acucobol			acu
+application/vnd.acucorp				atc acutc
+application/vnd.adobe.air-application-installer-package+zip	air
+application/vnd.adobe.fxp			fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml			xdp
+application/vnd.adobe.xfdf			xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space			ahead
+application/vnd.airzip.filesecure.azf		azf
+application/vnd.airzip.filesecure.azs		azs
+application/vnd.amazon.ebook			azw
+application/vnd.americandynamics.acc		acc
+application/vnd.amiga.ami			ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive		apk
+application/vnd.anser-web-certificate-issue-initiation	cii
+application/vnd.anser-web-funds-transfer-initiation	fti
+application/vnd.antix.game-component		atx
+application/vnd.apple.installer+xml		mpkg
+application/vnd.apple.mpegurl			m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi		swi
+application/vnd.audiograph			aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+application/vnd.blueice.multipass		mpm
+# application/vnd.bluetooth.ep.oob
+application/vnd.bmi				bmi
+application/vnd.businessobjects			rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+application/vnd.chemdraw+xml			cdxml
+application/vnd.chipnuts.karaoke-mmd		mmd
+application/vnd.cinderella			cdy
+# application/vnd.cirpack.isdn-ext
+application/vnd.claymore			cla
+application/vnd.cloanto.rp9			rp9
+application/vnd.clonk.c4group			c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config		c11amc
+application/vnd.cluetrust.cartomobile-config-pkg	c11amz
+# application/vnd.commerce-battelle
+application/vnd.commonspace			csp
+application/vnd.contact.cmsg			cdbcmsg
+application/vnd.cosmocaller			cmc
+application/vnd.crick.clicker			clkx
+application/vnd.crick.clicker.keyboard		clkk
+application/vnd.crick.clicker.palette		clkp
+application/vnd.crick.clicker.template		clkt
+application/vnd.crick.clicker.wordbank		clkw
+application/vnd.criticaltools.wbs+xml		wbs
+application/vnd.ctc-posml			pml
+# application/vnd.ctct.ws+xml
+# application/vnd.cups-pdf
+# application/vnd.cups-postscript
+application/vnd.cups-ppd			ppd
+# application/vnd.cups-raster
+# application/vnd.cups-raw
+application/vnd.curl.car			car
+application/vnd.curl.pcurl			pcurl
+# application/vnd.cybank
+application/vnd.data-vision.rdz			rdz
+application/vnd.dece.data			uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml			uvt uvvt
+application/vnd.dece.unspecified		uvx uvvx
+application/vnd.denovo.fcselayout-link		fe_launch
+# application/vnd.dir-bi.plate-dl-nosuffix
+application/vnd.dna				dna
+application/vnd.dolby.mlp			mlp
+# application/vnd.dolby.mobile.1
+# application/vnd.dolby.mobile.2
+application/vnd.dpgraph				dpg
+application/vnd.dreamfactory			dfac
+application/vnd.dvb.ait				ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service			svc
+# application/vnd.dxr
+application/vnd.dynageo				geo
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart			mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven				nml
+application/vnd.epson.esf			esf
+application/vnd.epson.msf			msf
+application/vnd.epson.quickanime		qam
+application/vnd.epson.salt			slt
+application/vnd.epson.ssf			ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml			es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album			ez2
+application/vnd.ezpix-package			ez3
+# application/vnd.f-secure.mobile
+application/vnd.fdf				fdf
+application/vnd.fdsn.mseed			mseed
+application/vnd.fdsn.seed			seed dataless
+# application/vnd.ffsns
+# application/vnd.fints
+application/vnd.flographit			gph
+application/vnd.fluxtime.clip			ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker			fm frame maker book
+application/vnd.frogans.fnc			fnc
+application/vnd.frogans.ltf			ltf
+application/vnd.fsc.weblaunch			fsc
+application/vnd.fujitsu.oasys			oas
+application/vnd.fujitsu.oasys2			oa2
+application/vnd.fujitsu.oasys3			oa3
+application/vnd.fujitsu.oasysgp			fg5
+application/vnd.fujitsu.oasysprs		bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+# application/vnd.fujixerox.hbpl
+application/vnd.fujixerox.ddd			ddd
+application/vnd.fujixerox.docuworks		xdw
+application/vnd.fujixerox.docuworks.binder	xbd
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet			fzs
+application/vnd.genomatix.tuxedo		txd
+# application/vnd.geocube+xml
+application/vnd.geogebra.file			ggb
+application/vnd.geogebra.tool			ggt
+application/vnd.geometry-explorer		gex gre
+application/vnd.geonext				gxt
+application/vnd.geoplan				g2w
+application/vnd.geospace			g3w
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx				gmx
+application/vnd.google-earth.kml+xml		kml
+application/vnd.google-earth.kmz		kmz
+application/vnd.grafeq				gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account			gac
+application/vnd.groove-help			ghf
+application/vnd.groove-identity-message		gim
+application/vnd.groove-injector			grv
+application/vnd.groove-tool-message		gtm
+application/vnd.groove-tool-template		tpl
+application/vnd.groove-vcard			vcg
+application/vnd.hal+xml				hal
+application/vnd.handheld-entertainment+xml	zmm
+application/vnd.hbci				hbci
+# application/vnd.hcl-bireports
+application/vnd.hhe.lesson-player		les
+application/vnd.hp-hpgl				hpgl
+application/vnd.hp-hpid				hpid
+application/vnd.hp-hps				hps
+application/vnd.hp-jlyt				jlt
+application/vnd.hp-pcl				pcl
+application/vnd.hp-pclxl			pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data		sfd-hdstx
+application/vnd.hzn-3d-crossword		x3d
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay			mpy
+application/vnd.ibm.modcap			afp listafp list3820
+application/vnd.ibm.rights-management		irm
+application/vnd.ibm.secure-container		sc
+application/vnd.iccprofile			icc icm
+application/vnd.igloader			igl
+application/vnd.immervision-ivp			ivp
+application/vnd.immervision-ivu			ivu
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+application/vnd.insors.igm			igm
+application/vnd.intercon.formnet		xpw xpx
+application/vnd.intergeo			i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo			qbo
+application/vnd.intu.qfx			qfx
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.packageitem+xml
+application/vnd.ipunplugged.rcprofile		rcprofile
+application/vnd.irepository.package+xml		irp
+application/vnd.is-xpr				xpr
+application/vnd.isac.fcs			fcs
+application/vnd.jam				jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms		rms
+application/vnd.jisp				jisp
+application/vnd.joost.joda-archive		joda
+application/vnd.kahootz				ktz ktr
+application/vnd.kde.karbon			karbon
+application/vnd.kde.kchart			chrt
+application/vnd.kde.kformula			kfo
+application/vnd.kde.kivio			flw
+application/vnd.kde.kontour			kon
+application/vnd.kde.kpresenter			kpr kpt
+application/vnd.kde.kspread			ksp
+application/vnd.kde.kword			kwd kwt
+application/vnd.kenameaapp			htke
+application/vnd.kidspiration			kia
+application/vnd.kinar				kne knp
+application/vnd.koan				skp skd skt skm
+application/vnd.kodak-descriptor		sse
+application/vnd.las.las+xml			lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop	lbd
+application/vnd.llamagraphics.life-balance.exchange+xml	lbe
+application/vnd.lotus-1-2-3			123
+application/vnd.lotus-approach			apr
+application/vnd.lotus-freelance			pre
+application/vnd.lotus-notes			nsf
+application/vnd.lotus-organizer			org
+application/vnd.lotus-screencam			scm
+application/vnd.lotus-wordpro			lwp
+application/vnd.macports.portpkg		portpkg
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+application/vnd.mcd				mcd
+application/vnd.medcalcdata			mc1
+application/vnd.mediastation.cdkey		cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer				mwf
+application/vnd.mfmp				mfm
+application/vnd.micrografx.flo			flo
+application/vnd.micrografx.igx			igx
+application/vnd.mif				mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf			daf
+application/vnd.mobius.dis			dis
+application/vnd.mobius.mbk			mbk
+application/vnd.mobius.mqy			mqy
+application/vnd.mobius.msl			msl
+application/vnd.mobius.plc			plc
+application/vnd.mobius.txf			txf
+application/vnd.mophun.application		mpn
+application/vnd.mophun.certificate		mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml			xul
+application/vnd.ms-artgalry			cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed		cab
+application/vnd.ms-excel			xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12		xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb
+application/vnd.ms-excel.sheet.macroenabled.12		xlsm
+application/vnd.ms-excel.template.macroenabled.12	xltm
+application/vnd.ms-fontobject			eot
+application/vnd.ms-htmlhelp			chm
+application/vnd.ms-ims				ims
+application/vnd.ms-lrm				lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme			thmx
+application/vnd.ms-pki.seccat			cat
+application/vnd.ms-pki.stl			stl
+# application/vnd.ms-playready.initiator+xml
+application/vnd.ms-powerpoint			ppt pps pot
+application/vnd.ms-powerpoint.addin.macroenabled.12		ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12	pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12		sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12		ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12		potm
+application/vnd.ms-project			mpp mpt
+# application/vnd.ms-tnef
+# application/vnd.ms-wmdrm.lic-chlg-req
+# application/vnd.ms-wmdrm.lic-resp
+# application/vnd.ms-wmdrm.meter-chlg-req
+# application/vnd.ms-wmdrm.meter-resp
+application/vnd.ms-word.document.macroenabled.12	docm
+application/vnd.ms-word.template.macroenabled.12	dotm
+application/vnd.ms-works			wps wks wcm wdb
+application/vnd.ms-wpl				wpl
+application/vnd.ms-xpsdocument			xps
+application/vnd.mseq				mseq
+# application/vnd.msign
+# application/vnd.multiad.creator
+# application/vnd.multiad.creator.cif
+# application/vnd.music-niff
+application/vnd.musician			mus
+application/vnd.muvee.style			msty
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu		nlu
+application/vnd.noblenet-directory		nnd
+application/vnd.noblenet-sealer			nns
+application/vnd.noblenet-web			nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data		ngdat
+application/vnd.nokia.n-gage.symbian.install	n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset		rpst
+application/vnd.nokia.radio-presets		rpss
+application/vnd.novadigm.edm			edm
+application/vnd.novadigm.edx			edx
+application/vnd.novadigm.ext			ext
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart		odc
+application/vnd.oasis.opendocument.chart-template	otc
+application/vnd.oasis.opendocument.database		odb
+application/vnd.oasis.opendocument.formula		odf
+application/vnd.oasis.opendocument.formula-template	odft
+application/vnd.oasis.opendocument.graphics		odg
+application/vnd.oasis.opendocument.graphics-template	otg
+application/vnd.oasis.opendocument.image		odi
+application/vnd.oasis.opendocument.image-template	oti
+application/vnd.oasis.opendocument.presentation		odp
+application/vnd.oasis.opendocument.presentation-template	otp
+application/vnd.oasis.opendocument.spreadsheet		ods
+application/vnd.oasis.opendocument.spreadsheet-template	ots
+application/vnd.oasis.opendocument.text			odt
+application/vnd.oasis.opendocument.text-master		odm
+application/vnd.oasis.opendocument.text-template	ott
+application/vnd.oasis.opendocument.text-web		oth
+# application/vnd.obn
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar			xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml			dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+application/vnd.openofficeorg.extension		oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide	sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template	potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.quobject-quoxdocument
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package		mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp				dp
+# application/vnd.otps.ct-kip+xml
+application/vnd.palm				pdb pqa oprc
+# application/vnd.paos.xml
+application/vnd.pawaafile			paw
+application/vnd.pg.format			str
+application/vnd.pg.osasli			ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel				efif
+application/vnd.pmi.widget			wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn			plf
+application/vnd.powerbuilder6			pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box		box
+application/vnd.proteus.magazine		mgz
+application/vnd.publishare-delta-tree		qps
+application/vnd.pvi.ptid1			ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed			bed
+application/vnd.recordare.musicxml		mxl
+application/vnd.recordare.musicxml+xml		musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote			cryptonote
+application/vnd.rim.cod				cod
+application/vnd.rn-realmedia			rm
+application/vnd.route66.link66+xml		link66
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track		st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail				see
+application/vnd.sema				sema
+application/vnd.semd				semd
+application/vnd.semf				semf
+application/vnd.shana.informed.formdata		ifm
+application/vnd.shana.informed.formtemplate	itp
+application/vnd.shana.informed.interchange	iif
+application/vnd.shana.informed.package		ipk
+application/vnd.simtech-mindmapper		twd twds
+application/vnd.smaf				mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher			teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml			sdkm sdkd
+application/vnd.spotfire.dxp			dxp
+application/vnd.spotfire.sfs			sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc		sdc
+application/vnd.stardivision.draw		sda
+application/vnd.stardivision.impress		sdd
+application/vnd.stardivision.math		smf
+application/vnd.stardivision.writer		sdw vor
+application/vnd.stardivision.writer-global	sgl
+application/vnd.stepmania.stepchart		sm
+# application/vnd.street-stream
+application/vnd.sun.xml.calc			sxc
+application/vnd.sun.xml.calc.template		stc
+application/vnd.sun.xml.draw			sxd
+application/vnd.sun.xml.draw.template		std
+application/vnd.sun.xml.impress			sxi
+application/vnd.sun.xml.impress.template	sti
+application/vnd.sun.xml.math			sxm
+application/vnd.sun.xml.writer			sxw
+application/vnd.sun.xml.writer.global		sxg
+application/vnd.sun.xml.writer.template		stw
+# application/vnd.sun.wadl+xml
+application/vnd.sus-calendar			sus susp
+application/vnd.svd				svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install			sis sisx
+application/vnd.syncml+xml			xsm
+application/vnd.syncml.dm+wbxml			bdm
+application/vnd.syncml.dm+xml			xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive	tao
+application/vnd.tmobile-livetv			tmo
+application/vnd.trid.tpt			tpt
+application/vnd.triscape.mxs			mxs
+application/vnd.trueapp				tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl				ufd ufdl
+application/vnd.uiq.theme			utz
+application/vnd.umajin				umj
+application/vnd.unity				unityweb
+application/vnd.uoml+xml			uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+application/vnd.vcx				vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio				vsd vst vss vsw
+application/vnd.visionary			vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf				vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml			wbxml
+application/vnd.wap.wmlc			wmlc
+application/vnd.wap.wmlscriptc			wmlsc
+application/vnd.webturbo			wtb
+# application/vnd.wfa.wsc
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player			nbp
+application/vnd.wordperfect			wpd
+application/vnd.wqd				wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf				stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+application/vnd.xara				xar
+application/vnd.xfdl				xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic			hvd
+application/vnd.yamaha.hv-script		hvs
+application/vnd.yamaha.hv-voice			hvp
+application/vnd.yamaha.openscoreformat			osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio		saf
+application/vnd.yamaha.smaf-phrase		spf
+# application/vnd.yamaha.tunnel-udpencap
+application/vnd.yellowriver-custom-menu		cmp
+application/vnd.zul				zir zirz
+application/vnd.zzazz.deck+xml			zaz
+application/voicexml+xml			vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget				wgt
+application/winhlp				hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml				wsdl
+application/wspolicy+xml			wspolicy
+application/x-7z-compressed			7z
+application/x-abiword				abw
+application/x-ace-compressed			ace
+application/x-authorware-bin			aab x32 u32 vox
+application/x-authorware-map			aam
+application/x-authorware-seg			aas
+application/x-bcpio				bcpio
+application/x-bittorrent			torrent
+application/x-bzip				bz
+application/x-bzip2				bz2 boz
+application/x-cdlink				vcd
+application/x-chat				chat
+application/x-chess-pgn				pgn
+# application/x-compress
+application/x-cpio				cpio
+application/x-csh				csh
+application/x-debian-package			deb udeb
+application/x-director			dir dcr dxr cst cct cxt w3d fgd swa
+application/x-doom				wad
+application/x-dtbncx+xml			ncx
+application/x-dtbook+xml			dtb
+application/x-dtbresource+xml			res
+application/x-dvi				dvi
+application/x-font-bdf				bdf
+# application/x-font-dos
+# application/x-font-framemaker
+application/x-font-ghostscript			gsf
+# application/x-font-libgrx
+application/x-font-linux-psf			psf
+application/x-font-otf				otf
+application/x-font-pcf				pcf
+application/x-font-snf				snf
+# application/x-font-speedo
+# application/x-font-sunos-news
+application/x-font-ttf				ttf ttc
+application/x-font-type1			pfa pfb pfm afm
+application/x-font-woff				woff
+# application/x-font-vfont
+application/x-futuresplash			spl
+application/x-gnumeric				gnumeric
+application/x-gtar				gtar
+# application/x-gzip
+application/x-hdf				hdf
+application/x-java-jnlp-file			jnlp
+application/x-latex				latex
+application/x-mobipocket-ebook			prc mobi
+application/x-ms-application			application
+application/x-ms-wmd				wmd
+application/x-ms-wmz				wmz
+application/x-ms-xbap				xbap
+application/x-msaccess				mdb
+application/x-msbinder				obd
+application/x-mscardfile			crd
+application/x-msclip				clp
+application/x-msdownload			exe dll com bat msi
+application/x-msmediaview			mvb m13 m14
+application/x-msmetafile			wmf
+application/x-msmoney				mny
+application/x-mspublisher			pub
+application/x-msschedule			scd
+application/x-msterminal			trm
+application/x-mswrite				wri
+application/x-netcdf				nc cdf
+application/x-pkcs12				p12 pfx
+application/x-pkcs7-certificates		p7b spc
+application/x-pkcs7-certreqresp			p7r
+application/x-rar-compressed			rar
+application/x-sh				sh
+application/x-shar				shar
+application/x-shockwave-flash			swf
+application/x-silverlight-app			xap
+application/x-stuffit				sit
+application/x-stuffitx				sitx
+application/x-sv4cpio				sv4cpio
+application/x-sv4crc				sv4crc
+application/x-tar				tar
+application/x-tcl				tcl
+application/x-tex				tex
+application/x-tex-tfm				tfm
+application/x-texinfo				texinfo texi
+application/x-ustar				ustar
+application/x-wais-source			src
+application/x-x509-ca-cert			der crt
+application/x-xfig				fig
+application/x-xpinstall				xpi
+# application/x400-bp
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml			xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info-diff+xml
+# application/xcon-conference-info+xml
+application/xenc+xml				xenc
+application/xhtml+xml				xhtml xht
+# application/xhtml-voice+xml
+application/xml					xml xsl
+application/xml-dtd				dtd
+# application/xml-external-parsed-entity
+# application/xmpp+xml
+application/xop+xml				xop
+application/xslt+xml				xslt
+application/xspf+xml				xspf
+application/xv+xml				mxml xhvml xvml xvm
+application/yang				yang
+application/yin+xml				yin
+application/zip					zip
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm					adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic					au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dvi4
+# audio/eac3
+# audio/evrc
+# audio/evrc-qcp
+# audio/evrc0
+# audio/evrc1
+# audio/evrcb
+# audio/evrcb0
+# audio/evrcb1
+# audio/evrcwb
+# audio/evrcwb0
+# audio/evrcwb1
+# audio/example
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/l16
+# audio/l20
+# audio/l24
+# audio/l8
+# audio/lpc
+audio/midi					mid midi kar rmi
+# audio/mobile-xmf
+audio/mp4					mp4a
+# audio/mp4a-latm
+# audio/mpa
+# audio/mpa-robust
+audio/mpeg					mpga mp2 mp2a mp3 m2a m3a
+# audio/mpeg4-generic
+audio/ogg					oga ogg spx
+# audio/parityfec
+# audio/pcma
+# audio/pcma-wb
+# audio/pcmu-wb
+# audio/pcmu
+# audio/prs.sid
+# audio/qcelp
+# audio/red
+# audio/rtp-enc-aescm128
+# audio/rtp-midi
+# audio/rtx
+# audio/smv
+# audio/smv0
+# audio/smv-qcp
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio				uva uvva
+audio/vnd.digital-winds				eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra					dra
+audio/vnd.dts					dts
+audio/vnd.dts.hd				dtshd
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice				lvp
+audio/vnd.ms-playready.media.pya		pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800			ecelp4800
+audio/vnd.nuera.ecelp7470			ecelp7470
+audio/vnd.nuera.ecelp9600			ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip					rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm					weba
+audio/x-aac					aac
+audio/x-aiff					aif aiff aifc
+audio/x-mpegurl					m3u
+audio/x-ms-wax					wax
+audio/x-ms-wma					wma
+audio/x-pn-realaudio				ram ra
+audio/x-pn-realaudio-plugin			rmp
+audio/x-wav					wav
+chemical/x-cdx					cdx
+chemical/x-cif					cif
+chemical/x-cmdf					cmdf
+chemical/x-cml					cml
+chemical/x-csml					csml
+# chemical/x-pdb
+chemical/x-xyz					xyz
+image/bmp					bmp
+image/cgm					cgm
+# image/example
+# image/fits
+image/g3fax					g3
+image/gif					gif
+image/ief					ief
+# image/jp2
+image/jpeg					jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx					ktx
+# image/naplps
+image/png					png
+image/prs.btif					btif
+# image/prs.pti
+image/svg+xml					svg svgz
+# image/t38
+image/tiff					tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop			psd
+# image/vnd.cns.inf2
+image/vnd.dece.graphic				uvi uvvi uvg uvvg
+image/vnd.dvb.subtitle				sub
+image/vnd.djvu					djvu djv
+image/vnd.dwg					dwg
+image/vnd.dxf					dxf
+image/vnd.fastbidsheet				fbs
+image/vnd.fpx					fpx
+image/vnd.fst					fst
+image/vnd.fujixerox.edmics-mmr			mmr
+image/vnd.fujixerox.edmics-rlc			rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+image/vnd.ms-modi				mdi
+image/vnd.net-fpx				npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+image/vnd.wap.wbmp				wbmp
+image/vnd.xiff					xif
+image/webp					webp
+image/x-cmu-raster				ras
+image/x-cmx					cmx
+image/x-freehand				fh fhc fh4 fh5 fh7
+image/x-icon					ico
+image/x-pcx					pcx
+image/x-pict					pic pct
+image/x-portable-anymap				pnm
+image/x-portable-bitmap				pbm
+image/x-portable-graymap			pgm
+image/x-portable-pixmap				ppm
+image/x-rgb					rgb
+image/x-xbitmap					xbm
+image/x-xpixmap					xpm
+image/x-xwindowdump				xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822					eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# model/example
+model/iges					igs iges
+model/mesh					msh mesh silo
+model/vnd.collada+xml				dae
+model/vnd.dwf					dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl					gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw					gtw
+# model/vnd.moml+xml
+model/vnd.mts					mts
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+model/vnd.vtu					vtu
+model/vrml					wrl vrml
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# text/1d-interleaved-parityfec
+text/calendar					ics ifb
+text/css					css
+text/csv					csv
+# text/directory
+# text/dns
+# text/ecmascript
+# text/enriched
+# text/example
+text/html					html htm
+# text/javascript
+text/n3						n3
+# text/parityfec
+text/plain					txt text conf def list log in
+# text/prs.fallenstein.rst
+text/prs.lines.tag				dsc
+# text/vnd.radisys.msml-basic-layout
+# text/red
+# text/rfc822-headers
+text/richtext					rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtx
+text/sgml					sgml sgm
+# text/t140
+text/tab-separated-values			tsv
+text/troff					t tr roff man me ms
+text/turtle					ttl
+# text/ulpfec
+text/uri-list					uri uris urls
+# text/vnd.abc
+text/vnd.curl					curl
+text/vnd.curl.dcurl				dcurl
+text/vnd.curl.scurl				scurl
+text/vnd.curl.mcurl				mcurl
+# text/vnd.dmclientscript
+# text/vnd.esmertec.theme-descriptor
+text/vnd.fly					fly
+text/vnd.fmi.flexstor				flx
+text/vnd.graphviz				gv
+text/vnd.in3d.3dml				3dml
+text/vnd.in3d.spot				spot
+# text/vnd.iptc.newsml
+# text/vnd.iptc.nitf
+# text/vnd.latex-z
+# text/vnd.motorola.reflex
+# text/vnd.ms-mediapackage
+# text/vnd.net2phone.commcenter.command
+# text/vnd.si.uricatalogue
+text/vnd.sun.j2me.app-descriptor		jad
+# text/vnd.trolltech.linguist
+# text/vnd.wap.si
+# text/vnd.wap.sl
+text/vnd.wap.wml				wml
+text/vnd.wap.wmlscript				wmls
+text/x-asm					s asm
+text/x-c					c cc cxx cpp h hh dic
+text/x-fortran					f for f77 f90
+text/x-pascal					p pas
+text/x-java-source				java
+text/x-setext					etx
+text/x-uuencode					uu
+text/x-vcalendar				vcs
+text/x-vcard					vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp					3gp
+# video/3gpp-tt
+video/3gpp2					3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/example
+video/h261					h261
+video/h263					h263
+# video/h263-1998
+# video/h263-2000
+video/h264					h264
+# video/h264-rcdo
+# video/h264-svc
+video/jpeg					jpgv
+# video/jpeg2000
+video/jpm					jpm jpgm
+video/mj2					mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4					mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg					mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg					ogv
+# video/parityfec
+# video/pointer
+video/quicktime					qt mov
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd				uvh uvvh
+video/vnd.dece.mobile				uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd				uvp uvvp
+video/vnd.dece.sd				uvs uvvs
+video/vnd.dece.video				uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.fvt					fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl				mxu m4u
+video/vnd.ms-playready.media.pyv		pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4				uvu uvvu
+video/vnd.vivo					viv
+video/webm					webm
+video/x-f4v					f4v
+video/x-fli					fli
+video/x-flv					flv
+video/x-m4v					m4v
+video/x-ms-asf					asf asx
+video/x-ms-wm					wm
+video/x-ms-wmv					wmv
+video/x-ms-wmx					wmx
+video/x-ms-wvx					wvx
+video/x-msvideo					avi
+video/x-sgi-movie				movie
+x-conference/x-cooltalk				ice
diff --git a/weinre.server/node_modules/express/node_modules/mime/types/node.types b/weinre.server/node_modules/express/node_modules/mime/types/node.types
new file mode 100644
index 0000000..fdabaa4
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mime/types/node.types
@@ -0,0 +1,43 @@
+# What: Google Chrome Extension
+# Why: To allow apps to (work) be served with the right content type header.
+# http://codereview.chromium.org/2830017
+# Added by: niftylettuce
+application/x-chrome-extension  crx
+
+# What: OTF Message Silencer
+# Why: To silence the "Resource interpreted as font but transferred with MIME
+# type font/otf" message that occurs in Google Chrome
+# Added by: niftylettuce
+font/opentype  otf
+
+# What: HTC support
+# Why: To properly render .htc files such as CSS3PIE
+# Added by: niftylettuce
+text/x-component  htc
+
+# What: HTML5 application cache manifest
+# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
+# per https://developer.mozilla.org/en/offline_resources_in_firefox
+# Added by: louisremi
+text/cache-manifest  appcache manifest
+
+# What: node binary buffer format
+# Why: semi-standard extension w/in the node community
+# Added by: tootallnate
+application/octet-stream  buffer
+
+# What: The "protected" MP-4 formats used by iTunes.
+# Why: Required for streaming music to browsers (?)
+# Added by: broofa
+application/mp4  m4p
+audio/mp4  m4a
+
+# What: Music playlist format (http://en.wikipedia.org/wiki/M3U)
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+application/x-mpegURL  m3u8
+
+# What: Video format, Part of RFC1890
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+video/MP2T  ts
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore
new file mode 100644
index 0000000..9303c34
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.orig b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.orig
new file mode 100644
index 0000000..9303c34
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.orig
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.rej b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.rej
new file mode 100644
index 0000000..69244ff
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/.gitignore.rej
@@ -0,0 +1,5 @@
+--- /dev/null
++++ .gitignore
+@@ -0,0 +1,2 @@
++node_modules/
++npm-debug.log
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/LICENSE b/weinre.server/node_modules/express/node_modules/mkdirp/LICENSE
new file mode 100644
index 0000000..432d1ae
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/README.markdown b/weinre.server/node_modules/express/node_modules/mkdirp/README.markdown
new file mode 100644
index 0000000..0393c4e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/README.markdown
@@ -0,0 +1,21 @@
+mkdirp
+======
+
+Like `mkdir -p`, but in node.js!
+
+Example
+=======
+
+pow.js
+------
+    var mkdirp = require('mkdirp');
+    
+    mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+        if (err) console.error(err)
+        else console.log('pow!')
+    });
+
+Output
+    pow!
+
+And now /tmp/foo/bar/baz exists, huzzah!
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js
new file mode 100644
index 0000000..7741462
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+    if (err) console.error(err)
+    else console.log('pow!')
+});
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.orig b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.orig
new file mode 100644
index 0000000..7741462
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.orig
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+    if (err) console.error(err)
+    else console.log('pow!')
+});
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.rej b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.rej
new file mode 100644
index 0000000..81e7f43
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/examples/pow.js.rej
@@ -0,0 +1,19 @@
+--- examples/pow.js
++++ examples/pow.js
+@@ -1,6 +1,15 @@
+-var mkdirp = require('mkdirp').mkdirp;
++var mkdirp = require('../').mkdirp,
++    mkdirpSync = require('../').mkdirpSync;
+ 
+ mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+     if (err) console.error(err)
+     else console.log('pow!')
+ });
++
++try {
++  mkdirpSync('/tmp/bar/foo/baz', 0755);
++  console.log('double pow!');
++}
++catch (ex) {
++  console.log(ex);
++}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/index.js b/weinre.server/node_modules/express/node_modules/mkdirp/index.js
new file mode 100644
index 0000000..30e9600
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/index.js
@@ -0,0 +1,20 @@
+var path = require('path');
+var fs = require('fs');
+
+var exports = module.exports = function mkdirP (p, mode, f) {
+    var cb = f || function () {};
+    p = path.resolve(p);
+    
+    var ps = path.normalize(p).split('/');
+    path.exists(p, function (exists) {
+        if (exists) cb(null);
+        else mkdirP(ps.slice(0,-1).join('/'), mode, function (err) {
+            if (err && err.code !== 'EEXIST') cb(err)
+            else fs.mkdir(p, mode, function (err) {
+                if (err && err.code !== 'EEXIST') cb(err)
+                else cb()
+            });
+        });
+    });
+};
+exports.mkdirp = exports.mkdirP = module.exports;
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/test/mkdirp.js b/weinre.server/node_modules/express/node_modules/mkdirp/test/mkdirp.js
new file mode 100644
index 0000000..b07cd70
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/test/mkdirp.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('woo', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var file = '/tmp/' + [x,y,z].join('/');
+    
+    mkdirp(file, 0755, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    t.equal(stat.mode & 0777, 0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/test/race.js b/weinre.server/node_modules/express/node_modules/mkdirp/test/race.js
new file mode 100644
index 0000000..96a0447
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/test/race.js
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('race', function (t) {
+    t.plan(4);
+    var ps = [ '', 'tmp' ];
+    
+    for (var i = 0; i < 25; i++) {
+        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+        ps.push(dir);
+    }
+    var file = ps.join('/');
+    
+    var res = 2;
+    mk(file, function () {
+        if (--res === 0) t.end();
+    });
+    
+    mk(file, function () {
+        if (--res === 0) t.end();
+    });
+    
+    function mk (file, cb) {
+        mkdirp(file, 0755, function (err) {
+            if (err) t.fail(err);
+            else path.exists(file, function (ex) {
+                if (!ex) t.fail('file not created')
+                else fs.stat(file, function (err, stat) {
+                    if (err) t.fail(err)
+                    else {
+                        t.equal(stat.mode & 0777, 0755);
+                        t.ok(stat.isDirectory(), 'target not a directory');
+                        if (cb) cb();
+                    }
+                })
+            })
+        });
+    }
+});
diff --git a/weinre.server/node_modules/express/node_modules/mkdirp/test/rel.js b/weinre.server/node_modules/express/node_modules/mkdirp/test/rel.js
new file mode 100644
index 0000000..7985824
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/mkdirp/test/rel.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('rel', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var cwd = process.cwd();
+    process.chdir('/tmp');
+    
+    var file = [x,y,z].join('/');
+    
+    mkdirp(file, 0755, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    process.chdir(cwd);
+                    t.equal(stat.mode & 0777, 0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
diff --git a/weinre.server/node_modules/express/node_modules/qs/.gitmodules b/weinre.server/node_modules/express/node_modules/qs/.gitmodules
new file mode 100644
index 0000000..49e31da
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "support/expresso"]
+	path = support/expresso
+	url = git://github.com/visionmedia/expresso.git
+[submodule "support/should"]
+	path = support/should
+	url = git://github.com/visionmedia/should.js.git
diff --git a/weinre.server/node_modules/express/node_modules/qs/.npmignore b/weinre.server/node_modules/express/node_modules/qs/.npmignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/.npmignore
@@ -0,0 +1 @@
+node_modules
diff --git a/weinre.server/node_modules/express/node_modules/qs/.travis.yml b/weinre.server/node_modules/express/node_modules/qs/.travis.yml
new file mode 100644
index 0000000..2c0a8f6
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.4
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/History.md b/weinre.server/node_modules/express/node_modules/qs/History.md
new file mode 100644
index 0000000..3eaf7df
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/History.md
@@ -0,0 +1,73 @@
+
+0.4.2 / 2012-02-08 
+==================
+
+  * Fixed: ensure objects are created when appropriate not arrays [aheckmann]
+
+0.4.1 / 2012-01-26 
+==================
+
+  * Fixed stringify()ing numbers. Closes #23
+
+0.4.0 / 2011-11-21 
+==================
+
+  * Allow parsing of an existing object (for `bodyParser()`) [jackyz]
+  * Replaced expresso with mocha
+
+0.3.2 / 2011-11-08 
+==================
+
+  * Fixed global variable leak
+
+0.3.1 / 2011-08-17 
+==================
+
+  * Added `try/catch` around malformed uri components
+  * Add test coverage for Array native method bleed-though
+
+0.3.0 / 2011-07-19 
+==================
+
+  * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart]
+
+0.2.0 / 2011-06-29 
+==================
+
+  * Added `qs.stringify()` [Cory Forsyth]
+
+0.1.0 / 2011-04-13 
+==================
+
+  * Added jQuery-ish array support
+
+0.0.7 / 2011-03-13 
+==================
+
+  * Fixed; handle empty string and `== null` in `qs.parse()` [dmit]
+    allows for convenient `qs.parse(url.parse(str).query)`
+
+0.0.6 / 2011-02-14 
+==================
+
+  * Fixed; support for implicit arrays
+
+0.0.4 / 2011-02-09 
+==================
+
+  * Fixed `+` as a space
+
+0.0.3 / 2011-02-08 
+==================
+
+  * Fixed case when right-hand value contains "]"
+
+0.0.2 / 2011-02-07 
+==================
+
+  * Fixed "=" presence in key
+
+0.0.1 / 2011-02-07 
+==================
+
+  * Initial release
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/Makefile b/weinre.server/node_modules/express/node_modules/qs/Makefile
new file mode 100644
index 0000000..e4df837
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/Makefile
@@ -0,0 +1,5 @@
+
+test:
+	@./node_modules/.bin/mocha
+
+.PHONY: test
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/Readme.md b/weinre.server/node_modules/express/node_modules/qs/Readme.md
new file mode 100644
index 0000000..db0d145
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/Readme.md
@@ -0,0 +1,54 @@
+# node-querystring
+
+  query string parser for node supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
+
+## Installation
+
+    $ npm install qs
+
+## Examples
+
+```js
+var qs = require('qs');
+
+qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
+// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
+
+qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
+// => user[name]=Tobi&user[email]=tobi%40learnboost.com
+```
+
+## Testing
+
+Install dev dependencies:
+
+    $ npm install -d
+
+and execute:
+
+    $ make test
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/benchmark.js b/weinre.server/node_modules/express/node_modules/qs/benchmark.js
new file mode 100644
index 0000000..97e2c93
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/benchmark.js
@@ -0,0 +1,17 @@
+
+var qs = require('./');
+
+var times = 100000
+  , start = new Date
+  , n = times;
+
+console.log('times: %d', times);
+
+while (n--) qs.parse('foo=bar');
+console.log('simple: %dms', new Date - start);
+
+var start = new Date
+  , n = times;
+
+while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log('nested: %dms', new Date - start);
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/examples.js b/weinre.server/node_modules/express/node_modules/qs/examples.js
new file mode 100644
index 0000000..27617b7
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/examples.js
@@ -0,0 +1,51 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('./');
+
+var obj = qs.parse('foo');
+console.log(obj)
+
+var obj = qs.parse('foo=bar=baz');
+console.log(obj)
+
+var obj = qs.parse('users[]');
+console.log(obj)
+
+var obj = qs.parse('name=tj&email=tj@vision-media.ca');
+console.log(obj)
+
+var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('a=a&a=b&a=c');
+console.log(obj)
+
+var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[1]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[foo]=TJ');
+console.log(obj)
+
+var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }});
+console.log(str);
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/index.js b/weinre.server/node_modules/express/node_modules/qs/index.js
new file mode 100644
index 0000000..d177d20
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/querystring');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/node_modules/qs/lib/querystring.js b/weinre.server/node_modules/express/node_modules/qs/lib/querystring.js
new file mode 100644
index 0000000..6c72712
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/lib/querystring.js
@@ -0,0 +1,264 @@
+
+/*!
+ * querystring
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Library version.
+ */
+
+exports.version = '0.4.2';
+
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = {};
+  var t = {};
+  for (var i in parent[key]) t[i] = parent[key][i];
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (Array.isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (Array.isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[Object.keys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~part.indexOf(']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~key.indexOf(']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && Array.isArray(parent.base)) {
+      var t = {};
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+  Object.keys(obj).forEach(function(name){
+    merge(ret, name, obj[name]);
+  });
+  return ret.base;
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  return String(str)
+    .split('&')
+    .reduce(function(ret, pair){
+      try{
+        pair = decodeURIComponent(pair.replace(/\+/g, ' '));
+      } catch(e) {
+        // ignore
+      }
+
+      var eql = pair.indexOf('=')
+        , brace = lastBraceInKey(pair)
+        , key = pair.substr(0, brace || eql)
+        , val = pair.substr(brace || eql, pair.length)
+        , val = val.substr(val.indexOf('=') + 1, val.length);
+
+      // ?foo
+      if ('' == key) key = pair, val = '';
+
+      return merge(ret, key, val);
+    }, { base: {} }).base;
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (Array.isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + obj;
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '[]'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = Object.keys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    ret.push(stringify(obj[key], prefix
+      ? prefix + '[' + encodeURIComponent(key) + ']'
+      : encodeURIComponent(key)));
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (Array.isArray(v)) {
+    v.push(val);
+  } else {
+    obj[key] = [v, val];
+  }
+}
+
+/**
+ * Locate last brace in `str` within the key.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function lastBraceInKey(str) {
+  var len = str.length
+    , brace
+    , c;
+  for (var i = 0; i < len; ++i) {
+    c = str[i];
+    if (']' == c) brace = false;
+    if ('[' == c) brace = true;
+    if ('=' == c && !brace) return i;
+  }
+}
diff --git a/weinre.server/node_modules/express/node_modules/qs/test/mocha.opts b/weinre.server/node_modules/express/node_modules/qs/test/mocha.opts
new file mode 100644
index 0000000..521cbb2
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/test/mocha.opts
@@ -0,0 +1,2 @@
+--require should
+--ui exports
diff --git a/weinre.server/node_modules/express/node_modules/qs/test/parse.js b/weinre.server/node_modules/express/node_modules/qs/test/parse.js
new file mode 100644
index 0000000..f219e27
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/test/parse.js
@@ -0,0 +1,167 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('../');
+
+module.exports = {
+  'test basics': function(){
+    qs.parse('0=foo').should.eql({ '0': 'foo' });
+
+    qs.parse('foo=c++')
+      .should.eql({ foo: 'c  ' });
+
+    qs.parse('a[>=]=23')
+      .should.eql({ a: { '>=': '23' }});
+
+    qs.parse('a[<=>]==23')
+      .should.eql({ a: { '<=>': '=23' }});
+
+    qs.parse('a[==]=23')
+      .should.eql({ a: { '==': '23' }});
+
+    qs.parse('foo')
+      .should.eql({ foo: '' });
+
+    qs.parse('foo=bar')
+      .should.eql({ foo: 'bar' });
+
+    qs.parse('foo%3Dbar=baz')
+      .should.eql({ foo: 'bar=baz' });
+
+    qs.parse(' foo = bar = baz ')
+      .should.eql({ ' foo ': ' bar = baz ' });
+
+    qs.parse('foo=bar=baz')
+      .should.eql({ foo: 'bar=baz' });
+
+    qs.parse('foo=bar&bar=baz')
+      .should.eql({ foo: 'bar', bar: 'baz' });
+
+    qs.parse('foo=bar&baz')
+      .should.eql({ foo: 'bar', baz: '' });
+
+    qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World')
+      .should.eql({
+          cht: 'p3'
+        , chd: 't:60,40'
+        , chs: '250x100'
+        , chl: 'Hello|World'
+      });
+  },
+  
+  'test nesting': function(){
+    qs.parse('ops[>=]=25')
+      .should.eql({ ops: { '>=': '25' }});
+
+    qs.parse('user[name]=tj')
+      .should.eql({ user: { name: 'tj' }});
+
+    qs.parse('user[name][first]=tj&user[name][last]=holowaychuk')
+      .should.eql({ user: { name: { first: 'tj', last: 'holowaychuk' }}});
+  },
+  
+  'test escaping': function(){
+    qs.parse('foo=foo%20bar')
+      .should.eql({ foo: 'foo bar' });
+  },
+  
+  'test arrays': function(){
+    qs.parse('images[]')
+      .should.eql({ images: [] });
+
+    qs.parse('user[]=tj')
+      .should.eql({ user: ['tj'] });
+
+    qs.parse('user[]=tj&user[]=tobi&user[]=jane')
+      .should.eql({ user: ['tj', 'tobi', 'jane'] });
+
+    qs.parse('user[names][]=tj&user[names][]=tyler')
+      .should.eql({ user: { names: ['tj', 'tyler'] }});
+
+    qs.parse('user[names][]=tj&user[names][]=tyler&user[email]=tj@vision-media.ca')
+      .should.eql({ user: { names: ['tj', 'tyler'], email: 'tj@vision-media.ca' }});
+
+    qs.parse('items=a&items=b')
+      .should.eql({ items: ['a', 'b'] });
+
+    qs.parse('user[names]=tj&user[names]=holowaychuk&user[names]=TJ')
+      .should.eql({ user: { names: ['tj', 'holowaychuk', 'TJ'] }});
+
+    qs.parse('user[name][first]=tj&user[name][first]=TJ')
+      .should.eql({ user: { name: { first: ['tj', 'TJ'] }}});
+
+    var o = qs.parse('existing[fcbaebfecc][name][last]=tj')
+    o.should.eql({ existing: { 'fcbaebfecc': { name: { last: 'tj' }}}})
+    Array.isArray(o.existing).should.be.false;
+  },
+
+  'test right-hand brackets': function(){
+    qs.parse('pets=["tobi"]')
+      .should.eql({ pets: '["tobi"]' });
+
+    qs.parse('operators=[">=", "<="]')
+      .should.eql({ operators: '[">=", "<="]' });
+
+    qs.parse('op[>=]=[1,2,3]')
+      .should.eql({ op: { '>=': '[1,2,3]' }});
+
+    qs.parse('op[>=]=[1,2,3]&op[=]=[[[[1]]]]')
+          .should.eql({ op: { '>=': '[1,2,3]', '=': '[[[[1]]]]' }});
+  },
+  
+  'test duplicates': function(){
+    qs.parse('items=bar&items=baz&items=raz')
+      .should.eql({ items: ['bar', 'baz', 'raz'] });
+  },
+
+  'test empty': function(){
+    qs.parse('').should.eql({});
+    qs.parse(undefined).should.eql({});
+    qs.parse(null).should.eql({});
+  },
+
+  'test arrays with indexes': function(){
+    qs.parse('foo[0]=bar&foo[1]=baz').should.eql({ foo: ['bar', 'baz'] });
+    qs.parse('foo[1]=bar&foo[0]=baz').should.eql({ foo: ['baz', 'bar'] });
+    qs.parse('foo[base64]=RAWR').should.eql({ foo: { base64: 'RAWR' }});
+    qs.parse('foo[64base]=RAWR').should.eql({ foo: { '64base': 'RAWR' }});
+  },
+
+  'test arrays becoming objects': function(){
+    qs.parse('foo[0]=bar&foo[bad]=baz').should.eql({ foo: { 0: "bar", bad: "baz" }});
+    qs.parse('foo[bad]=baz&foo[0]=bar').should.eql({ foo: { 0: "bar", bad: "baz" }});
+  },
+
+  'test bleed-through of Array native properties/methods': function(){
+    Array.prototype.protoProperty = true;
+    Array.prototype.protoFunction = function () {};
+    qs.parse('foo=bar').should.eql({ foo: 'bar' });
+  },
+
+  'test malformed uri': function(){
+    qs.parse('{%:%}').should.eql({ '{%:%}': '' });
+    qs.parse('foo=%:%}').should.eql({ 'foo': '%:%}' });
+  },
+
+  'test semi-parsed': function(){
+    qs.parse({ 'user[name]': 'tobi' })
+      .should.eql({ user: { name: 'tobi' }});
+
+    qs.parse({ 'user[name]': 'tobi', 'user[email][main]': 'tobi@lb.com' })
+      .should.eql({ user: { name: 'tobi', email: { main: 'tobi@lb.com' } }});
+  }
+  
+  // 'test complex': function(){
+  //   qs.parse('users[][name][first]=tj&users[foo]=bar')
+  //     .should.eql({
+  //       users: [ { name: 'tj' }, { name: 'tobi' }, { foo: 'bar' }]
+  //     });
+  // 
+  //   qs.parse('users[][name][first]=tj&users[][name][first]=tobi')
+  //     .should.eql({
+  //       users: [ { name: 'tj' }, { name: 'tobi' }]
+  //     });
+  // }
+};
diff --git a/weinre.server/node_modules/express/node_modules/qs/test/stringify.js b/weinre.server/node_modules/express/node_modules/qs/test/stringify.js
new file mode 100644
index 0000000..c2195cb
--- /dev/null
+++ b/weinre.server/node_modules/express/node_modules/qs/test/stringify.js
@@ -0,0 +1,103 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('../')
+  , should = require('should')
+  , str_identities = {
+    'basics': [
+      { str: 'foo=bar', obj: {'foo' : 'bar'}},
+      { str: 'foo=%22bar%22', obj: {'foo' : '\"bar\"'}},
+      { str: 'foo=', obj: {'foo': ''}},
+      { str: 'foo=1&bar=2', obj: {'foo' : '1', 'bar' : '2'}},
+      { str: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', obj: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
+      { str: 'foo%3Dbaz=bar', obj: {'foo=baz': 'bar'}},
+      { str: 'foo=bar&bar=baz', obj: {foo: 'bar', bar: 'baz'}}
+    ],
+    'escaping': [
+      { str: 'foo=foo%20bar', obj: {foo: 'foo bar'}},
+      { str: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', obj: {
+          cht: 'p3'
+        , chd: 't:60,40'
+        , chs: '250x100'
+        , chl: 'Hello|World'
+      }}
+    ],
+    'nested': [
+      { str: 'foo[]=bar&foo[]=quux', obj: {'foo' : ['bar', 'quux']}},
+      { str: 'foo[]=bar', obj: {foo: ['bar']}},
+      { str: 'foo[]=1&foo[]=2', obj: {'foo' : ['1', '2']}},
+      { str: 'foo=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
+      { str: 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
+      { str: 'x[y][z]=1', obj: {'x' : {'y' : {'z' : '1'}}}},
+      { str: 'x[y][z][]=1', obj: {'x' : {'y' : {'z' : ['1']}}}},
+      { str: 'x[y][z]=2', obj: {'x' : {'y' : {'z' : '2'}}}},
+      { str: 'x[y][z][]=1&x[y][z][]=2', obj: {'x' : {'y' : {'z' : ['1', '2']}}}},
+      { str: 'x[y][][z]=1', obj: {'x' : {'y' : [{'z' : '1'}]}}},
+      { str: 'x[y][][z][]=1', obj: {'x' : {'y' : [{'z' : ['1']}]}}},
+      { str: 'x[y][][z]=1&x[y][][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
+      { str: 'x[y][][v][w]=1', obj: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
+      { str: 'x[y][][z]=1&x[y][][v][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
+      { str: 'x[y][][z]=1&x[y][][z]=2', obj: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
+      { str: 'x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3', obj: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
+      { str: 'user[name][first]=tj&user[name][last]=holowaychuk', obj: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
+    ],
+    'errors': [
+      { obj: 'foo=bar',     message: 'stringify expects an object' },
+      { obj: ['foo', 'bar'], message: 'stringify expects an object' }
+    ],
+    'numbers': [
+      { str: 'limit[]=1&limit[]=2&limit[]=3', obj: { limit: [1, 2, '3'] }},
+      { str: 'limit=1', obj: { limit: 1 }}
+    ]
+  };
+  
+
+// Assert error
+function err(fn, msg){
+  var err;
+  try {
+    fn();
+  } catch (e) {
+    should.equal(e.message, msg);
+    return;
+  }
+  throw new Error('no exception thrown, expected "' + msg + '"');
+}
+
+function test(type) {
+  var str, obj;
+  for (var i = 0; i < str_identities[type].length; i++) {
+    str = str_identities[type][i].str;
+    obj = str_identities[type][i].obj;
+    qs.stringify(obj).should.eql(str);
+  }
+}
+
+module.exports = {
+  'test basics': function() {
+    test('basics');
+  },
+
+  'test escaping': function() {
+    test('escaping');
+  },
+
+  'test nested': function() {
+    test('nested');
+  },
+  
+  'test numbers': function(){
+    test('numbers');
+  },
+
+  'test errors': function() {
+    var obj, message;
+    for (var i = 0; i < str_identities['errors'].length; i++) {
+      message = str_identities['errors'][i].message;
+      obj = str_identities['errors'][i].obj;
+      err(function(){ qs.stringify(obj) }, message);
+    }
+  }
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/foo/app.js b/weinre.server/node_modules/express/testing/foo/app.js
new file mode 100644
index 0000000..7574676
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/foo/app.js
@@ -0,0 +1,35 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('express')
+  , routes = require('./routes')
+
+var app = module.exports = express.createServer();
+
+// Configuration
+
+app.configure(function(){
+  app.set('views', __dirname + '/views');
+  app.set('view engine', 'jade');
+  app.use(express.bodyParser());
+  app.use(express.methodOverride());
+  app.use(app.router);
+  app.use(express.static(__dirname + '/public'));
+});
+
+app.configure('development', function(){
+  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
+});
+
+app.configure('production', function(){
+  app.use(express.errorHandler()); 
+});
+
+// Routes
+
+app.get('/', routes.index);
+
+app.listen(3000);
+console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
diff --git a/weinre.server/node_modules/express/testing/foo/public/stylesheets/style.css b/weinre.server/node_modules/express/testing/foo/public/stylesheets/style.css
new file mode 100644
index 0000000..30e047d
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/foo/public/stylesheets/style.css
@@ -0,0 +1,8 @@
+body {
+  padding: 50px;
+  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
+}
+
+a {
+  color: #00B7FF;
+}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/foo/routes/index.js b/weinre.server/node_modules/express/testing/foo/routes/index.js
new file mode 100644
index 0000000..0b2205c
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/foo/routes/index.js
@@ -0,0 +1,10 @@
+
+/*
+ * GET home page.
+ */
+
+exports.index = function(req, res){
+  res.writeHead(200);
+  req.doesnotexist();
+  // res.render('index', { title: 'Express' })
+};
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/foo/views/index.jade b/weinre.server/node_modules/express/testing/foo/views/index.jade
new file mode 100644
index 0000000..c9c35fa
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/foo/views/index.jade
@@ -0,0 +1,2 @@
+h1= title
+p Welcome to #{title}
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/foo/views/layout.jade b/weinre.server/node_modules/express/testing/foo/views/layout.jade
new file mode 100644
index 0000000..1a36941
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/foo/views/layout.jade
@@ -0,0 +1,6 @@
+!!!
+html
+  head
+    title= title
+    link(rel='stylesheet', href='/stylesheets/style.css')
+  body!= body
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/index.js b/weinre.server/node_modules/express/testing/index.js
new file mode 100644
index 0000000..3c5185d
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/index.js
@@ -0,0 +1,43 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('../')
+  , http = require('http')
+  , connect = require('connect');
+
+var app = express.createServer();
+
+app.get('/', function(req, res){
+  req.foo();
+  res.send('test');
+});
+
+// app.set('views', __dirname + '/views');
+// app.set('view engine', 'jade');
+// 
+// app.configure(function(){
+//   app.use(function(req, res, next){
+//     debugger
+//     res.write('first');
+//     console.error('first');
+//     next();
+//   });
+// 
+//   app.use(app.router);
+// 
+//   app.use(function(req, res, next){
+//     console.error('last');
+//     res.end('last');
+//   });
+// });
+// 
+// app.get('/', function(req, res, next){
+//   console.error('middle');
+//   res.write(' route ');
+//   next();
+// });
+
+app.listen(3000);
+console.log('listening on port 3000');
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/public/test.txt b/weinre.server/node_modules/express/testing/public/test.txt
new file mode 100644
index 0000000..cb9a165
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/public/test.txt
@@ -0,0 +1,2971 @@
+foo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+baz
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/views/page.html b/weinre.server/node_modules/express/testing/views/page.html
new file mode 100644
index 0000000..4ff9827
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/views/page.html
@@ -0,0 +1 @@
+p register test
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/views/page.jade b/weinre.server/node_modules/express/testing/views/page.jade
new file mode 100644
index 0000000..9c3f888
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/views/page.jade
@@ -0,0 +1,3 @@
+html
+  body
+    h1 test
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/views/test.md b/weinre.server/node_modules/express/testing/views/test.md
new file mode 100644
index 0000000..9139ff4
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/views/test.md
@@ -0,0 +1 @@
+testing _some_ markdown
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/views/user/index.jade b/weinre.server/node_modules/express/testing/views/user/index.jade
new file mode 100644
index 0000000..1b66a4f
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/views/user/index.jade
@@ -0,0 +1 @@
+p user page
\ No newline at end of file
diff --git a/weinre.server/node_modules/express/testing/views/user/list.jade b/weinre.server/node_modules/express/testing/views/user/list.jade
new file mode 100644
index 0000000..ed2b471
--- /dev/null
+++ b/weinre.server/node_modules/express/testing/views/user/list.jade
@@ -0,0 +1 @@
+p user list page
\ No newline at end of file
diff --git a/weinre.server/node_modules/nopt/.npmignore b/weinre.server/node_modules/nopt/.npmignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/weinre.server/node_modules/nopt/.npmignore
diff --git a/weinre.server/node_modules/nopt/LICENSE b/weinre.server/node_modules/nopt/LICENSE
new file mode 100644
index 0000000..05a4010
--- /dev/null
+++ b/weinre.server/node_modules/nopt/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/weinre.server/node_modules/nopt/README.md b/weinre.server/node_modules/nopt/README.md
new file mode 100644
index 0000000..eeddfd4
--- /dev/null
+++ b/weinre.server/node_modules/nopt/README.md
@@ -0,0 +1,208 @@
+If you want to write an option parser, and have it be good, there are
+two ways to do it.  The Right Way, and the Wrong Way.
+
+The Wrong Way is to sit down and write an option parser.  We've all done
+that.
+
+The Right Way is to write some complex configurable program with so many
+options that you go half-insane just trying to manage them all, and put
+it off with duct-tape solutions until you see exactly to the core of the
+problem, and finally snap and write an awesome option parser.
+
+If you want to write an option parser, don't write an option parser.
+Write a package manager, or a source control system, or a service
+restarter, or an operating system.  You probably won't end up with a
+good one of those, but if you don't give up, and you are relentless and
+diligent enough in your procrastination, you may just end up with a very
+nice option parser.
+
+## USAGE
+
+    // my-program.js
+    var nopt = require("nopt")
+      , Stream = require("stream").Stream
+      , path = require("path")
+      , knownOpts = { "foo" : [String, null]
+                    , "bar" : [Stream, Number]
+                    , "baz" : path
+                    , "bloo" : [ "big", "medium", "small" ]
+                    , "flag" : Boolean
+                    , "pick" : Boolean
+                    , "many" : [String, Array]
+                    }
+      , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
+                     , "b7" : ["--bar", "7"]
+                     , "m" : ["--bloo", "medium"]
+                     , "p" : ["--pick"]
+                     , "f" : ["--flag"]
+                     }
+                 // everything is optional.
+                 // knownOpts and shorthands default to {}
+                 // arg list defaults to process.argv
+                 // slice defaults to 2
+      , parsed = nopt(knownOpts, shortHands, process.argv, 2)
+    console.log(parsed)
+
+This would give you support for any of the following:
+
+```bash
+$ node my-program.js --foo "blerp" --no-flag
+{ "foo" : "blerp", "flag" : false }
+
+$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
+{ bar: 7, foo: "Mr. Hand", flag: true }
+
+$ node my-program.js --foo "blerp" -f -----p
+{ foo: "blerp", flag: true, pick: true }
+
+$ node my-program.js -fp --foofoo
+{ foo: "Mr. Foo", flag: true, pick: true }
+
+$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.
+{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
+
+$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.
+{ blatzk: 1000, flag: true, pick: true }
+
+$ node my-program.js --blatzk true -fp # but they need a value
+{ blatzk: true, flag: true, pick: true }
+
+$ node my-program.js --no-blatzk -fp # unless they start with "no-"
+{ blatzk: false, flag: true, pick: true }
+
+$ node my-program.js --baz b/a/z # known paths are resolved.
+{ baz: "/Users/isaacs/b/a/z" }
+
+# if Array is one of the types, then it can take many
+# values, and will always be an array.  The other types provided
+# specify what types are allowed in the list.
+
+$ node my-program.js --many 1 --many null --many foo
+{ many: ["1", "null", "foo"] }
+
+$ node my-program.js --many foo
+{ many: ["foo"] }
+```
+
+Read the tests at the bottom of `lib/nopt.js` for more examples of
+what this puppy can do.
+
+## Types
+
+The following types are supported, and defined on `nopt.typeDefs`
+
+* String: A normal string.  No parsing is done.
+* path: A file system path.  Gets resolved against cwd if not absolute.
+* url: A url.  If it doesn't parse, it isn't accepted.
+* Number: Must be numeric.
+* Date: Must parse as a date. If it does, and `Date` is one of the options,
+  then it will return a Date object, not a string.
+* Boolean: Must be either `true` or `false`.  If an option is a boolean,
+  then it does not need a value, and its presence will imply `true` as
+  the value.  To negate boolean flags, do `--no-whatever` or `--whatever
+  false`
+* NaN: Means that the option is strictly not allowed.  Any value will
+  fail.
+* Stream: An object matching the "Stream" class in node.  Valuable
+  for use when validating programmatically.  (npm uses this to let you
+  supply any WriteStream on the `outfd` and `logfd` config options.)
+* Array: If `Array` is specified as one of the types, then the value
+  will be parsed as a list of options.  This means that multiple values
+  can be specified, and that the value will always be an array.
+
+If a type is an array of values not on this list, then those are
+considered valid values.  For instance, in the example above, the
+`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
+and any other value will be rejected.
+
+When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
+interpreted as their JavaScript equivalents, and numeric values will be
+interpreted as a number.
+
+You can also mix types and values, or multiple types, in a list.  For
+instance `{ blah: [Number, null] }` would allow a value to be set to
+either a Number or null.
+
+To define a new type, add it to `nopt.typeDefs`.  Each item in that
+hash is an object with a `type` member and a `validate` method.  The
+`type` member is an object that matches what goes in the type list.  The
+`validate` method is a function that gets called with `validate(data,
+key, val)`.  Validate methods should assign `data[key]` to the valid
+value of `val` if it can be handled properly, or return boolean
+`false` if it cannot.
+
+You can also call `nopt.clean(data, types, typeDefs)` to clean up a
+config object and remove its invalid properties.
+
+## Error Handling
+
+By default, nopt outputs a warning to standard error when invalid
+options are found.  You can change this behavior by assigning a method
+to `nopt.invalidHandler`.  This method will be called with
+the offending `nopt.invalidHandler(key, val, types)`.
+
+If no `nopt.invalidHandler` is assigned, then it will console.error
+its whining.  If it is assigned to boolean `false` then the warning is
+suppressed.
+
+## Abbreviations
+
+Yes, they are supported.  If you define options like this:
+
+```javascript
+{ "foolhardyelephants" : Boolean
+, "pileofmonkeys" : Boolean }
+```
+
+Then this will work:
+
+```bash
+node program.js --foolhar --pil
+node program.js --no-f --pileofmon
+# etc.
+```
+
+## Shorthands
+
+Shorthands are a hash of shorter option names to a snippet of args that
+they expand to.
+
+If multiple one-character shorthands are all combined, and the
+combination does not unambiguously match any other option or shorthand,
+then they will be broken up into their constituent parts.  For example:
+
+```json
+{ "s" : ["--loglevel", "silent"]
+, "g" : "--global"
+, "f" : "--force"
+, "p" : "--parseable"
+, "l" : "--long"
+}
+```
+
+```bash
+npm ls -sgflp
+# just like doing this:
+npm ls --loglevel silent --global --force --long --parseable
+```
+
+## The Rest of the args
+
+The config object returned by nopt is given a special member called
+`argv`, which is an object with the following fields:
+
+* `remain`: The remaining args after all the parsing has occurred.
+* `original`: The args as they originally appeared.
+* `cooked`: The args after flags and shorthands are expanded.
+
+## Slicing
+
+Node programs are called with more or less the exact argv as it appears
+in C land, after the v8 and node-specific options have been plucked off.
+As such, `argv[0]` is always `node` and `argv[1]` is always the
+JavaScript program being run.
+
+That's usually not very useful to you.  So they're sliced off by
+default.  If you want them, then you can pass in `0` as the last
+argument, or any other number that you'd like to slice off the start of
+the list.
diff --git a/weinre.server/node_modules/nopt/bin/nopt.js b/weinre.server/node_modules/nopt/bin/nopt.js
new file mode 100755
index 0000000..df90c72
--- /dev/null
+++ b/weinre.server/node_modules/nopt/bin/nopt.js
@@ -0,0 +1,44 @@
+#!/usr/bin/env node
+var nopt = require("../lib/nopt")
+  , types = { num: Number
+            , bool: Boolean
+            , help: Boolean
+            , list: Array
+            , "num-list": [Number, Array]
+            , "str-list": [String, Array]
+            , "bool-list": [Boolean, Array]
+            , str: String }
+  , shorthands = { s: [ "--str", "astring" ]
+                 , b: [ "--bool" ]
+                 , nb: [ "--no-bool" ]
+                 , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ]
+                 , "?": ["--help"]
+                 , h: ["--help"]
+                 , H: ["--help"]
+                 , n: [ "--num", "125" ] }
+  , parsed = nopt( types
+                 , shorthands
+                 , process.argv
+                 , 2 )
+
+console.log("parsed", parsed)
+
+if (parsed.help) {
+  console.log("")
+  console.log("nopt cli tester")
+  console.log("")
+  console.log("types")
+  console.log(Object.keys(types).map(function M (t) {
+    var type = types[t]
+    if (Array.isArray(type)) {
+      return [t, type.map(function (type) { return type.name })]
+    }
+    return [t, type && type.name]
+  }).reduce(function (s, i) {
+    s[i[0]] = i[1]
+    return s
+  }, {}))
+  console.log("")
+  console.log("shorthands")
+  console.log(shorthands)
+}
diff --git a/weinre.server/node_modules/nopt/examples/my-program.js b/weinre.server/node_modules/nopt/examples/my-program.js
new file mode 100755
index 0000000..142447e
--- /dev/null
+++ b/weinre.server/node_modules/nopt/examples/my-program.js
@@ -0,0 +1,30 @@
+#!/usr/bin/env node
+
+//process.env.DEBUG_NOPT = 1
+
+// my-program.js
+var nopt = require("../lib/nopt")
+  , Stream = require("stream").Stream
+  , path = require("path")
+  , knownOpts = { "foo" : [String, null]
+                , "bar" : [Stream, Number]
+                , "baz" : path
+                , "bloo" : [ "big", "medium", "small" ]
+                , "flag" : Boolean
+                , "pick" : Boolean
+                }
+  , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
+                 , "b7" : ["--bar", "7"]
+                 , "m" : ["--bloo", "medium"]
+                 , "p" : ["--pick"]
+                 , "f" : ["--flag", "true"]
+                 , "g" : ["--flag"]
+                 , "s" : "--flag"
+                 }
+             // everything is optional.
+             // knownOpts and shorthands default to {}
+             // arg list defaults to process.argv
+             // slice defaults to 2
+  , parsed = nopt(knownOpts, shortHands, process.argv, 2)
+
+console.log("parsed =\n"+ require("util").inspect(parsed))
diff --git a/weinre.server/node_modules/nopt/lib/nopt.js b/weinre.server/node_modules/nopt/lib/nopt.js
new file mode 100644
index 0000000..ff802da
--- /dev/null
+++ b/weinre.server/node_modules/nopt/lib/nopt.js
@@ -0,0 +1,552 @@
+// info about each config option.
+
+var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
+  ? function () { console.error.apply(console, arguments) }
+  : function () {}
+
+var url = require("url")
+  , path = require("path")
+  , Stream = require("stream").Stream
+  , abbrev = require("abbrev")
+
+module.exports = exports = nopt
+exports.clean = clean
+
+exports.typeDefs =
+  { String  : { type: String,  validate: validateString  }
+  , Boolean : { type: Boolean, validate: validateBoolean }
+  , url     : { type: url,     validate: validateUrl     }
+  , Number  : { type: Number,  validate: validateNumber  }
+  , path    : { type: path,    validate: validatePath    }
+  , Stream  : { type: Stream,  validate: validateStream  }
+  , Date    : { type: Date,    validate: validateDate    }
+  }
+
+function nopt (types, shorthands, args, slice) {
+  args = args || process.argv
+  types = types || {}
+  shorthands = shorthands || {}
+  if (typeof slice !== "number") slice = 2
+
+  debug(types, shorthands, args, slice)
+
+  args = args.slice(slice)
+  var data = {}
+    , key
+    , remain = []
+    , cooked = args
+    , original = args.slice(0)
+
+  parse(args, data, remain, types, shorthands)
+  // now data is full
+  clean(data, types, exports.typeDefs)
+  data.argv = {remain:remain,cooked:cooked,original:original}
+  data.argv.toString = function () {
+    return this.original.map(JSON.stringify).join(" ")
+  }
+  return data
+}
+
+function clean (data, types, typeDefs) {
+  typeDefs = typeDefs || exports.typeDefs
+  var remove = {}
+    , typeDefault = [false, true, null, String, Number]
+
+  Object.keys(data).forEach(function (k) {
+    if (k === "argv") return
+    var val = data[k]
+      , isArray = Array.isArray(val)
+      , type = types[k]
+    if (!isArray) val = [val]
+    if (!type) type = typeDefault
+    if (type === Array) type = typeDefault.concat(Array)
+    if (!Array.isArray(type)) type = [type]
+
+    debug("val=%j", val)
+    debug("types=", type)
+    val = val.map(function (val) {
+      // if it's an unknown value, then parse false/true/null/numbers/dates
+      if (typeof val === "string") {
+        debug("string %j", val)
+        val = val.trim()
+        if ((val === "null" && ~type.indexOf(null))
+            || (val === "true" &&
+               (~type.indexOf(true) || ~type.indexOf(Boolean)))
+            || (val === "false" &&
+               (~type.indexOf(false) || ~type.indexOf(Boolean)))) {
+          val = JSON.parse(val)
+          debug("jsonable %j", val)
+        } else if (~type.indexOf(Number) && !isNaN(val)) {
+          debug("convert to number", val)
+          val = +val
+        } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) {
+          debug("convert to date", val)
+          val = new Date(val)
+        }
+      }
+
+      if (!types.hasOwnProperty(k)) {
+        return val
+      }
+
+      // allow `--no-blah` to set 'blah' to null if null is allowed
+      if (val === false && ~type.indexOf(null) &&
+          !(~type.indexOf(false) || ~type.indexOf(Boolean))) {
+        val = null
+      }
+
+      var d = {}
+      d[k] = val
+      debug("prevalidated val", d, val, types[k])
+      if (!validate(d, k, val, types[k], typeDefs)) {
+        if (exports.invalidHandler) {
+          exports.invalidHandler(k, val, types[k], data)
+        } else if (exports.invalidHandler !== false) {
+          debug("invalid: "+k+"="+val, types[k])
+        }
+        return remove
+      }
+      debug("validated val", d, val, types[k])
+      return d[k]
+    }).filter(function (val) { return val !== remove })
+
+    if (!val.length) delete data[k]
+    else if (isArray) {
+      debug(isArray, data[k], val)
+      data[k] = val
+    } else data[k] = val[0]
+
+    debug("k=%s val=%j", k, val, data[k])
+  })
+}
+
+function validateString (data, k, val) {
+  data[k] = String(val)
+}
+
+function validatePath (data, k, val) {
+  data[k] = path.resolve(String(val))
+  return true
+}
+
+function validateNumber (data, k, val) {
+  debug("validate Number %j %j %j", k, val, isNaN(val))
+  if (isNaN(val)) return false
+  data[k] = +val
+}
+
+function validateDate (data, k, val) {
+  debug("validate Date %j %j %j", k, val, Date.parse(val))
+  var s = Date.parse(val)
+  if (isNaN(s)) return false
+  data[k] = new Date(val)
+}
+
+function validateBoolean (data, k, val) {
+  if (val instanceof Boolean) val = val.valueOf()
+  else if (typeof val === "string") {
+    if (!isNaN(val)) val = !!(+val)
+    else if (val === "null" || val === "false") val = false
+    else val = true
+  } else val = !!val
+  data[k] = val
+}
+
+function validateUrl (data, k, val) {
+  val = url.parse(String(val))
+  if (!val.host) return false
+  data[k] = val.href
+}
+
+function validateStream (data, k, val) {
+  if (!(val instanceof Stream)) return false
+  data[k] = val
+}
+
+function validate (data, k, val, type, typeDefs) {
+  // arrays are lists of types.
+  if (Array.isArray(type)) {
+    for (var i = 0, l = type.length; i < l; i ++) {
+      if (type[i] === Array) continue
+      if (validate(data, k, val, type[i], typeDefs)) return true
+    }
+    delete data[k]
+    return false
+  }
+
+  // an array of anything?
+  if (type === Array) return true
+
+  // NaN is poisonous.  Means that something is not allowed.
+  if (type !== type) {
+    debug("Poison NaN", k, val, type)
+    delete data[k]
+    return false
+  }
+
+  // explicit list of values
+  if (val === type) {
+    debug("Explicitly allowed %j", val)
+    // if (isArray) (data[k] = data[k] || []).push(val)
+    // else data[k] = val
+    data[k] = val
+    return true
+  }
+
+  // now go through the list of typeDefs, validate against each one.
+  var ok = false
+    , types = Object.keys(typeDefs)
+  for (var i = 0, l = types.length; i < l; i ++) {
+    debug("test type %j %j %j", k, val, types[i])
+    var t = typeDefs[types[i]]
+    if (t && type === t.type) {
+      var d = {}
+      ok = false !== t.validate(d, k, val)
+      val = d[k]
+      if (ok) {
+        // if (isArray) (data[k] = data[k] || []).push(val)
+        // else data[k] = val
+        data[k] = val
+        break
+      }
+    }
+  }
+  debug("OK? %j (%j %j %j)", ok, k, val, types[i])
+
+  if (!ok) delete data[k]
+  return ok
+}
+
+function parse (args, data, remain, types, shorthands) {
+  debug("parse", args, data, remain)
+
+  var key = null
+    , abbrevs = abbrev(Object.keys(types))
+    , shortAbbr = abbrev(Object.keys(shorthands))
+
+  for (var i = 0; i < args.length; i ++) {
+    var arg = args[i]
+    debug("arg", arg)
+
+    if (arg.match(/^-{2,}$/)) {
+      // done with keys.
+      // the rest are args.
+      remain.push.apply(remain, args.slice(i + 1))
+      args[i] = "--"
+      break
+    }
+    if (arg.charAt(0) === "-") {
+      if (arg.indexOf("=") !== -1) {
+        var v = arg.split("=")
+        arg = v.shift()
+        v = v.join("=")
+        args.splice.apply(args, [i, 1].concat([arg, v]))
+      }
+      // see if it's a shorthand
+      // if so, splice and back up to re-parse it.
+      var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs)
+      debug("arg=%j shRes=%j", arg, shRes)
+      if (shRes) {
+        debug(arg, shRes)
+        args.splice.apply(args, [i, 1].concat(shRes))
+        if (arg !== shRes[0]) {
+          i --
+          continue
+        }
+      }
+      arg = arg.replace(/^-+/, "")
+      var no = false
+      while (arg.toLowerCase().indexOf("no-") === 0) {
+        no = !no
+        arg = arg.substr(3)
+      }
+
+      if (abbrevs[arg]) arg = abbrevs[arg]
+
+      var isArray = types[arg] === Array ||
+        Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1
+
+      var val
+        , la = args[i + 1]
+
+      var isBool = no ||
+        types[arg] === Boolean ||
+        Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 ||
+        (la === "false" &&
+         (types[arg] === null ||
+          Array.isArray(types[arg]) && ~types[arg].indexOf(null)))
+
+      if (isBool) {
+        // just set and move along
+        val = !no
+        // however, also support --bool true or --bool false
+        if (la === "true" || la === "false") {
+          val = JSON.parse(la)
+          la = null
+          if (no) val = !val
+          i ++
+        }
+
+        // also support "foo":[Boolean, "bar"] and "--foo bar"
+        if (Array.isArray(types[arg]) && la) {
+          if (~types[arg].indexOf(la)) {
+            // an explicit type
+            val = la
+            i ++
+          } else if ( la === "null" && ~types[arg].indexOf(null) ) {
+            // null allowed
+            val = null
+            i ++
+          } else if ( !la.match(/^-{2,}[^-]/) &&
+                      !isNaN(la) &&
+                      ~types[arg].indexOf(Number) ) {
+            // number
+            val = +la
+            i ++
+          } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) {
+            // string
+            val = la
+            i ++
+          }
+        }
+
+        if (isArray) (data[arg] = data[arg] || []).push(val)
+        else data[arg] = val
+
+        continue
+      }
+
+      if (la && la.match(/^-{2,}$/)) {
+        la = undefined
+        i --
+      }
+
+      val = la === undefined ? true : la
+      if (isArray) (data[arg] = data[arg] || []).push(val)
+      else data[arg] = val
+
+      i ++
+      continue
+    }
+    remain.push(arg)
+  }
+}
+
+function resolveShort (arg, shorthands, shortAbbr, abbrevs) {
+  // handle single-char shorthands glommed together, like
+  // npm ls -glp, but only if there is one dash, and only if
+  // all of the chars are single-char shorthands, and it's
+  // not a match to some other abbrev.
+  arg = arg.replace(/^-+/, '')
+  if (abbrevs[arg] && !shorthands[arg]) {
+    return null
+  }
+  if (shortAbbr[arg]) {
+    arg = shortAbbr[arg]
+  } else {
+    var singles = shorthands.___singles
+    if (!singles) {
+      singles = Object.keys(shorthands).filter(function (s) {
+        return s.length === 1
+      }).reduce(function (l,r) { l[r] = true ; return l }, {})
+      shorthands.___singles = singles
+    }
+    var chrs = arg.split("").filter(function (c) {
+      return singles[c]
+    })
+    if (chrs.join("") === arg) return chrs.map(function (c) {
+      return shorthands[c]
+    }).reduce(function (l, r) {
+      return l.concat(r)
+    }, [])
+  }
+
+  if (shorthands[arg] && !Array.isArray(shorthands[arg])) {
+    shorthands[arg] = shorthands[arg].split(/\s+/)
+  }
+  return shorthands[arg]
+}
+
+if (module === require.main) {
+var assert = require("assert")
+  , util = require("util")
+
+  , shorthands =
+    { s : ["--loglevel", "silent"]
+    , d : ["--loglevel", "info"]
+    , dd : ["--loglevel", "verbose"]
+    , ddd : ["--loglevel", "silly"]
+    , noreg : ["--no-registry"]
+    , reg : ["--registry"]
+    , "no-reg" : ["--no-registry"]
+    , silent : ["--loglevel", "silent"]
+    , verbose : ["--loglevel", "verbose"]
+    , h : ["--usage"]
+    , H : ["--usage"]
+    , "?" : ["--usage"]
+    , help : ["--usage"]
+    , v : ["--version"]
+    , f : ["--force"]
+    , desc : ["--description"]
+    , "no-desc" : ["--no-description"]
+    , "local" : ["--no-global"]
+    , l : ["--long"]
+    , p : ["--parseable"]
+    , porcelain : ["--parseable"]
+    , g : ["--global"]
+    }
+
+  , types =
+    { aoa: Array
+    , nullstream: [null, Stream]
+    , date: Date
+    , str: String
+    , browser : String
+    , cache : path
+    , color : ["always", Boolean]
+    , depth : Number
+    , description : Boolean
+    , dev : Boolean
+    , editor : path
+    , force : Boolean
+    , global : Boolean
+    , globalconfig : path
+    , group : [String, Number]
+    , gzipbin : String
+    , logfd : [Number, Stream]
+    , loglevel : ["silent","win","error","warn","info","verbose","silly"]
+    , long : Boolean
+    , "node-version" : [false, String]
+    , npaturl : url
+    , npat : Boolean
+    , "onload-script" : [false, String]
+    , outfd : [Number, Stream]
+    , parseable : Boolean
+    , pre: Boolean
+    , prefix: path
+    , proxy : url
+    , "rebuild-bundle" : Boolean
+    , registry : url
+    , searchopts : String
+    , searchexclude: [null, String]
+    , shell : path
+    , t: [Array, String]
+    , tag : String
+    , tar : String
+    , tmp : path
+    , "unsafe-perm" : Boolean
+    , usage : Boolean
+    , user : String
+    , username : String
+    , userconfig : path
+    , version : Boolean
+    , viewer: path
+    , _exit : Boolean
+    }
+
+; [["-v", {version:true}, []]
+  ,["---v", {version:true}, []]
+  ,["ls -s --no-reg connect -d",
+    {loglevel:"info",registry:null},["ls","connect"]]
+  ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]]
+  ,["ls --registry blargle", {}, ["ls"]]
+  ,["--no-registry", {registry:null}, []]
+  ,["--no-color true", {color:false}, []]
+  ,["--no-color false", {color:true}, []]
+  ,["--no-color", {color:false}, []]
+  ,["--color false", {color:false}, []]
+  ,["--color --logfd 7", {logfd:7,color:true}, []]
+  ,["--color=true", {color:true}, []]
+  ,["--logfd=10", {logfd:10}, []]
+  ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]]
+  ,["--tmp=tmp -tar=gtar",
+    {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]]
+  ,["--logfd x", {}, []]
+  ,["a -true -- -no-false", {true:true},["a","-no-false"]]
+  ,["a -no-false", {false:false},["a"]]
+  ,["a -no-no-true", {true:true}, ["a"]]
+  ,["a -no-no-no-false", {false:false}, ["a"]]
+  ,["---NO-no-No-no-no-no-nO-no-no"+
+    "-No-no-no-no-no-no-no-no-no"+
+    "-no-no-no-no-NO-NO-no-no-no-no-no-no"+
+    "-no-body-can-do-the-boogaloo-like-I-do"
+   ,{"body-can-do-the-boogaloo-like-I-do":false}, []]
+  ,["we are -no-strangers-to-love "+
+    "--you-know the-rules --and so-do-i "+
+    "---im-thinking-of=a-full-commitment "+
+    "--no-you-would-get-this-from-any-other-guy "+
+    "--no-gonna-give-you-up "+
+    "-no-gonna-let-you-down=true "+
+    "--no-no-gonna-run-around false "+
+    "--desert-you=false "+
+    "--make-you-cry false "+
+    "--no-tell-a-lie "+
+    "--no-no-and-hurt-you false"
+   ,{"strangers-to-love":false
+    ,"you-know":"the-rules"
+    ,"and":"so-do-i"
+    ,"you-would-get-this-from-any-other-guy":false
+    ,"gonna-give-you-up":false
+    ,"gonna-let-you-down":false
+    ,"gonna-run-around":false
+    ,"desert-you":false
+    ,"make-you-cry":false
+    ,"tell-a-lie":false
+    ,"and-hurt-you":false
+    },["we", "are"]]
+  ,["-t one -t two -t three"
+   ,{t: ["one", "two", "three"]}
+   ,[]]
+  ,["-t one -t null -t three four five null"
+   ,{t: ["one", "null", "three"]}
+   ,["four", "five", "null"]]
+  ,["-t foo"
+   ,{t:["foo"]}
+   ,[]]
+  ,["--no-t"
+   ,{t:["false"]}
+   ,[]]
+  ,["-no-no-t"
+   ,{t:["true"]}
+   ,[]]
+  ,["-aoa one -aoa null -aoa 100"
+   ,{aoa:["one", null, 100]}
+   ,[]]
+  ,["-str 100"
+   ,{str:"100"}
+   ,[]]
+  ,["--color always"
+   ,{color:"always"}
+   ,[]]
+  ,["--no-nullstream"
+   ,{nullstream:null}
+   ,[]]
+  ,["--nullstream false"
+   ,{nullstream:null}
+   ,[]]
+  ,["--notadate 2011-01-25"
+   ,{notadate: "2011-01-25"}
+   ,[]]
+  ,["--date 2011-01-25"
+   ,{date: new Date("2011-01-25")}
+   ,[]]
+  ].forEach(function (test) {
+    var argv = test[0].split(/\s+/)
+      , opts = test[1]
+      , rem = test[2]
+      , actual = nopt(types, shorthands, argv, 0)
+      , parsed = actual.argv
+    delete actual.argv
+    console.log(util.inspect(actual, false, 2, true), parsed.remain)
+    for (var i in opts) {
+      var e = JSON.stringify(opts[i])
+        , a = JSON.stringify(actual[i] === undefined ? null : actual[i])
+      if (e && typeof e === "object") {
+        assert.deepEqual(e, a)
+      } else {
+        assert.equal(e, a)
+      }
+    }
+    assert.deepEqual(rem, parsed.remain)
+  })
+}
diff --git a/weinre.server/node_modules/nopt/node_modules/abbrev/README.md b/weinre.server/node_modules/nopt/node_modules/abbrev/README.md
new file mode 100644
index 0000000..99746fe
--- /dev/null
+++ b/weinre.server/node_modules/nopt/node_modules/abbrev/README.md
@@ -0,0 +1,23 @@
+# abbrev-js
+
+Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
+
+Usage:
+
+    var abbrev = require("abbrev");
+    abbrev("foo", "fool", "folding", "flop");
+    
+    // returns:
+    { fl: 'flop'
+    , flo: 'flop'
+    , flop: 'flop'
+    , fol: 'folding'
+    , fold: 'folding'
+    , foldi: 'folding'
+    , foldin: 'folding'
+    , folding: 'folding'
+    , foo: 'foo'
+    , fool: 'fool'
+    }
+
+This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.
diff --git a/weinre.server/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/weinre.server/node_modules/nopt/node_modules/abbrev/lib/abbrev.js
new file mode 100644
index 0000000..037de2d
--- /dev/null
+++ b/weinre.server/node_modules/nopt/node_modules/abbrev/lib/abbrev.js
@@ -0,0 +1,106 @@
+
+module.exports = exports = abbrev.abbrev = abbrev
+
+abbrev.monkeyPatch = monkeyPatch
+
+function monkeyPatch () {
+  Array.prototype.abbrev = function () { return abbrev(this) }
+  Object.prototype.abbrev = function () { return abbrev(Object.keys(this)) }
+}
+
+function abbrev (list) {
+  if (arguments.length !== 1 || !Array.isArray(list)) {
+    list = Array.prototype.slice.call(arguments, 0)
+  }
+  for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
+    args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
+  }
+
+  // sort them lexicographically, so that they're next to their nearest kin
+  args = args.sort(lexSort)
+
+  // walk through each, seeing how much it has in common with the next and previous
+  var abbrevs = {}
+    , prev = ""
+  for (var i = 0, l = args.length ; i < l ; i ++) {
+    var current = args[i]
+      , next = args[i + 1] || ""
+      , nextMatches = true
+      , prevMatches = true
+    if (current === next) continue
+    for (var j = 0, cl = current.length ; j < cl ; j ++) {
+      var curChar = current.charAt(j)
+      nextMatches = nextMatches && curChar === next.charAt(j)
+      prevMatches = prevMatches && curChar === prev.charAt(j)
+      if (nextMatches || prevMatches) continue
+      else {
+        j ++
+        break
+      }
+    }
+    prev = current
+    if (j === cl) {
+      abbrevs[current] = current
+      continue
+    }
+    for (var a = current.substr(0, j) ; j <= cl ; j ++) {
+      abbrevs[a] = current
+      a += current.charAt(j)
+    }
+  }
+  return abbrevs
+}
+
+function lexSort (a, b) {
+  return a === b ? 0 : a > b ? 1 : -1
+}
+
+
+// tests
+if (module === require.main) {
+
+var assert = require("assert")
+  , sys
+sys = require("util")
+
+console.log("running tests")
+function test (list, expect) {
+  var actual = abbrev(list)
+  assert.deepEqual(actual, expect,
+    "abbrev("+sys.inspect(list)+") === " + sys.inspect(expect) + "\n"+
+    "actual: "+sys.inspect(actual))
+  actual = abbrev.apply(exports, list)
+  assert.deepEqual(abbrev.apply(exports, list), expect,
+    "abbrev("+list.map(JSON.stringify).join(",")+") === " + sys.inspect(expect) + "\n"+
+    "actual: "+sys.inspect(actual))
+}
+
+test([ "ruby", "ruby", "rules", "rules", "rules" ],
+{ rub: 'ruby'
+, ruby: 'ruby'
+, rul: 'rules'
+, rule: 'rules'
+, rules: 'rules'
+})
+test(["fool", "foom", "pool", "pope"],
+{ fool: 'fool'
+, foom: 'foom'
+, poo: 'pool'
+, pool: 'pool'
+, pop: 'pope'
+, pope: 'pope'
+})
+test(["a", "ab", "abc", "abcd", "abcde", "acde"],
+{ a: 'a'
+, ab: 'ab'
+, abc: 'abc'
+, abcd: 'abcd'
+, abcde: 'abcde'
+, ac: 'acde'
+, acd: 'acde'
+, acde: 'acde'
+})
+
+console.log("pass")
+
+}
diff --git a/weinre.server/node_modules/underscore/.npmignore b/weinre.server/node_modules/underscore/.npmignore
new file mode 100644
index 0000000..2ce2684
--- /dev/null
+++ b/weinre.server/node_modules/underscore/.npmignore
@@ -0,0 +1,3 @@
+test/
+Rakefile
+docs/
\ No newline at end of file
diff --git a/weinre.server/node_modules/underscore/LICENSE b/weinre.server/node_modules/underscore/LICENSE
new file mode 100644
index 0000000..61d28c0
--- /dev/null
+++ b/weinre.server/node_modules/underscore/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/weinre.server/node_modules/underscore/README.md b/weinre.server/node_modules/underscore/README.md
new file mode 100644
index 0000000..a6564a2
--- /dev/null
+++ b/weinre.server/node_modules/underscore/README.md
@@ -0,0 +1,19 @@
+                       __                                                         
+                      /\ \                                                         __           
+     __  __    ___    \_\ \     __   _ __   ____    ___    ___   _ __    __       /\_\    ____  
+    /\ \/\ \ /' _ `\  /'_  \  /'__`\/\  __\/ ,__\  / ___\ / __`\/\  __\/'__`\     \/\ \  /',__\ 
+    \ \ \_\ \/\ \/\ \/\ \ \ \/\  __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\  __/  __  \ \ \/\__, `\
+     \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
+      \/___/  \/_/\/_/\/__,_ /\/____/ \/_/ \/___/  \/____/\/___/  \/_/ \/____/\/_//\ \_\ \/___/ 
+                                                                                  \ \____/      
+                                                                                   \/___/
+                                                                               
+Underscore.js is a utility-belt library for JavaScript that provides 
+support for the usual functional suspects (each, map, reduce, filter...) 
+without extending any core JavaScript objects.
+
+For Docs, License, Tests, and pre-packed downloads, see:
+http://documentcloud.github.com/underscore/
+
+Many thanks to our contributors:
+https://github.com/documentcloud/underscore/contributors
diff --git a/weinre.server/node_modules/underscore/index.html b/weinre.server/node_modules/underscore/index.html
new file mode 100644
index 0000000..52c9671
--- /dev/null
+++ b/weinre.server/node_modules/underscore/index.html
@@ -0,0 +1,1975 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+  <meta http-equiv="X-UA-Compatible" content="chrome=1">
+  <title>Underscore.js</title>
+  <style>
+    body {
+      font-size: 14px;
+      line-height: 22px;
+      background: #f4f4f4 url(docs/images/background.png);
+      color: #000;
+      font-family: Helvetica Neue, Helvetica, Arial;      
+    }
+    .interface {
+      font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
+    }
+    div#sidebar {
+      background: #fff;
+      position: fixed;
+      top: 0; left: 0; bottom: 0;
+      width: 200px;
+      overflow-y: auto;
+      overflow-x: hidden;
+      padding: 15px 0 30px 30px;
+      border-right: 1px solid #bbb;
+      box-shadow: 0 0 20px #ccc; -webkit-box-shadow: 0 0 20px #ccc; -moz-box-shadow: 0 0 20px #ccc;
+    }
+    a.toc_title, a.toc_title:visited {
+      display: block;
+      color: black;
+      font-weight: bold;
+      margin-top: 15px;
+    }
+      a.toc_title:hover {
+        text-decoration: underline;
+      }
+      #sidebar .version {
+        font-size: 10px;
+        font-weight: normal;
+      }
+    ul.toc_section {
+      font-size: 11px;
+      line-height: 14px;
+      margin: 5px 0 0 0;
+      padding-left: 0px;
+      list-style-type: none;
+      font-family: Lucida Grande;
+    }
+      .toc_section li {
+        cursor: pointer;
+        margin: 0 0 3px 0;
+      }
+        .toc_section li a {
+          text-decoration: none;
+          color: black;
+        }
+          .toc_section li a:hover {
+            text-decoration: underline;
+          }  
+    div.container {
+      width: 550px;
+      margin: 40px 0 50px 260px;
+    }
+    div.warning {
+      margin-top: 15px;
+      font: bold 11px Arial;
+      color: #770000;
+    }
+    p {
+      margin: 20px 0;
+      width: 550px;
+    }
+    a, a:visited {
+      color: #444;
+    }
+    a:active, a:hover {
+      color: #000;
+    }
+    h1, h2, h3, h4, h5, h6 {
+      padding-top: 20px;
+    }
+      h2 {
+        font-size: 20px;
+      }
+    b.header {
+      font-size: 16px;
+      line-height: 30px;
+    }
+    span.alias {
+      font-size: 14px;
+      font-style: italic;
+      margin-left: 20px;
+    }
+    table, tr, td {
+      margin: 0; padding: 0;
+    }
+      td {
+        padding: 2px 12px 2px 0;
+      }
+    ul {
+      list-style-type: circle;
+      padding: 0 0 0 20px;
+    }
+      li {
+        width: 500px;
+        margin-bottom: 10px;
+      }
+      code, pre, tt {
+        font-family: Monaco, Consolas, "Lucida Console", monospace;
+        font-size: 12px;
+        line-height: 18px;
+        font-style: normal;
+      }
+        tt {
+          padding: 0px 3px;
+          background: #fff;
+          border: 1px solid #ddd;
+          zoom: 1;
+        }
+        code {
+          margin-left: 20px;
+        }
+        pre {
+          font-size: 12px;
+          padding: 2px 0 2px 15px;
+          border-left: 5px solid #bbb;
+          margin: 0px 0 30px;
+        }
+  </style>
+</head>
+<body>
+  
+  <div id="sidebar" class="interface">
+
+    <a class="toc_title" href="#">
+      Underscore.js <span class="version">(1.3.1)</span>
+    </a>
+    
+    <a class="toc_title" href="#">
+      Introduction
+    </a>
+
+    <a class="toc_title" href="#collections">
+      Collections
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#each">each</a></li>
+      <li>- <a href="#map">map</a></li>
+      <li>- <a href="#reduce">reduce</a></li>
+      <li>- <a href="#reduceRight">reduceRight</a></li>
+      <li>- <a href="#find">find</a></li>
+      <li>- <a href="#filter">filter</a></li>
+      <li>- <a href="#reject">reject</a></li>
+      <li>- <a href="#all">all</a></li>
+      <li>- <a href="#any">any</a></li>
+      <li>- <a href="#include">include</a></li>
+      <li>- <a href="#invoke">invoke</a></li>
+      <li>- <a href="#pluck">pluck</a></li>
+      <li>- <a href="#max">max</a></li>
+      <li>- <a href="#min">min</a></li>
+      <li>- <a href="#sortBy">sortBy</a></li>
+      <li>- <a href="#groupBy">groupBy</a></li>
+      <li>- <a href="#sortedIndex">sortedIndex</a></li>
+      <li>- <a href="#shuffle">shuffle</a></li>
+      <li>- <a href="#toArray">toArray</a></li>
+      <li>- <a href="#size">size</a></li>
+    </ul>
+
+    <a class="toc_title" href="#arrays">
+      Arrays
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#first">first</a></li>
+      <li>- <a href="#initial">initial</a></li>
+      <li>- <a href="#last">last</a></li>
+      <li>- <a href="#rest">rest</a></li>
+      <li>- <a href="#compact">compact</a></li>
+      <li>- <a href="#flatten">flatten</a></li>
+      <li>- <a href="#without">without</a></li>
+      <li>- <a href="#union">union</a></li>
+      <li>- <a href="#intersection">intersection</a></li>
+      <li>- <a href="#difference">difference</a></li>
+      <li>- <a href="#uniq">uniq</a></li>
+      <li>- <a href="#zip">zip</a></li>
+      <li>- <a href="#indexOf">indexOf</a></li>
+      <li>- <a href="#lastIndexOf">lastIndexOf</a></li>
+      <li>- <a href="#range">range</a></li>
+    </ul>
+
+    <a class="toc_title" href="#functions">
+      Functions
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#bind">bind</a></li>
+      <li>- <a href="#bindAll">bindAll</a></li>
+      <li>- <a href="#memoize">memoize</a></li>
+      <li>- <a href="#delay">delay</a></li>
+      <li>- <a href="#defer">defer</a></li>
+      <li>- <a href="#throttle">throttle</a></li>
+      <li>- <a href="#debounce">debounce</a></li>
+      <li>- <a href="#once">once</a></li>
+      <li>- <a href="#after">after</a></li>
+      <li>- <a href="#wrap">wrap</a></li>
+      <li>- <a href="#compose">compose</a></li>
+    </ul>
+
+    <a class="toc_title" href="#objects">
+      Objects
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#keys">keys</a></li>
+      <li>- <a href="#values">values</a></li>
+      <li>- <a href="#functions">functions</a></li>
+      <li>- <a href="#extend">extend</a></li>
+      <li>- <a href="#defaults">defaults</a></li>
+      <li>- <a href="#clone">clone</a></li>
+      <li>- <a href="#tap">tap</a></li>
+      <li>- <a href="#has">has</a></li>
+      <li>- <a href="#isEqual">isEqual</a></li>
+      <li>- <a href="#isEmpty">isEmpty</a></li>
+      <li>- <a href="#isElement">isElement</a></li>
+      <li>- <a href="#isArray">isArray</a></li>
+      <li>- <a href="#isArguments">isArguments</a></li>
+      <li>- <a href="#isFunction">isFunction</a></li>
+      <li>- <a href="#isString">isString</a></li>
+      <li>- <a href="#isNumber">isNumber</a></li>
+      <li>- <a href="#isBoolean">isBoolean</a></li>
+      <li>- <a href="#isDate">isDate</a></li>
+      <li>- <a href="#isRegExp">isRegExp</a></li>
+      <li>- <a href="#isNaN">isNaN</a></li>
+      <li>- <a href="#isNull">isNull</a></li>
+      <li>- <a href="#isUndefined">isUndefined</a></li>
+    </ul>
+
+    <a class="toc_title" href="#utility">
+      Utility
+    </a>    
+    <ul class="toc_section">
+      <li>- <a href="#noConflict">noConflict</a></li>
+      <li>- <a href="#identity">identity</a></li>
+      <li>- <a href="#times">times</a></li>
+      <li>- <a href="#mixin">mixin</a></li>
+      <li>- <a href="#uniqueId">uniqueId</a></li>
+      <li>- <a href="#escape">escape</a></li>
+      <li>- <a href="#template">template</a></li>
+    </ul>
+
+    <a class="toc_title" href="#chaining">
+      Chaining
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#chain">chain</a></li>
+      <li>- <a href="#value">value</a></li>
+    </ul>
+    
+    <a class="toc_title" href="#links">
+      Links
+    </a>
+    
+    <a class="toc_title" href="#changelog">
+      Change Log
+    </a>
+    
+  </div>
+
+  <div class="container">
+
+    <p id="introduction">
+      <img style="width: 396px; height: 69px;" src="docs/images/underscore.png" alt="Underscore.js" />
+    </p>
+
+    <p>
+      <a href="http://github.com/documentcloud/underscore/">Underscore</a> is a
+      utility-belt library for JavaScript that provides a lot of the
+      functional programming support that you would expect in
+      <a href="http://prototypejs.org/api">Prototype.js</a>
+      (or <a href="http://www.ruby-doc.org/core/classes/Enumerable.html">Ruby</a>),
+      but without extending any of the built-in JavaScript objects. It's the
+      tie to go along with <a href="http://docs.jquery.com">jQuery</a>'s tux,
+      and <a href="http://backbonejs.org">Backbone.js</a>'s suspenders.
+    </p>
+
+    <p>
+      Underscore provides 60-odd functions that support both the usual
+      functional suspects: <b>map</b>, <b>select</b>, <b>invoke</b> &mdash;
+      as well as more specialized helpers: function binding, javascript
+      templating, deep equality testing, and so on. It delegates to built-in
+      functions, if present, so modern browsers will use the
+      native implementations of <b>forEach</b>, <b>map</b>, <b>reduce</b>,
+      <b>filter</b>, <b>every</b>, <b>some</b> and <b>indexOf</b>.
+    </p>
+
+    <p>
+      A complete <a href="test/test.html">Test &amp; Benchmark Suite</a>
+      is included for your perusal.
+    </p>
+    
+    <p>
+      You may also read through the <a href="docs/underscore.html">annotated source code</a>.
+    </p>
+
+    <p>
+      The project is
+      <a href="http://github.com/documentcloud/underscore/">hosted on GitHub</a>.
+      You can report bugs and discuss features on the
+      <a href="http://github.com/documentcloud/underscore/issues">issues page</a>,
+      on Freenode in the <tt>#documentcloud</tt> channel,
+      or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>.
+    </p>
+
+    <p>
+      <i>Underscore is an open-source component of <a href="http://documentcloud.org/">DocumentCloud</a>.</i>
+    </p>
+
+    <h2>Downloads <i style="padding-left: 12px; font-size:12px;">(Right-click, and use "Save As")</i></h2>
+
+    <table>
+      <tr>
+        <td><a href="underscore.js">Development Version (1.3.1)</a></td>
+        <td><i>34kb, Uncompressed with Comments</i></td>
+      </tr>
+      <tr>
+        <td><a href="underscore-min.js">Production Version (1.3.1)</a></td>
+        <td><i>&lt; 4kb, Minified and Gzipped</i></td>
+      </tr>
+    </table>
+    
+    <div class="warning">Upgrade warning: version 1.3.0 removes AMD (RequireJS) support.</div>
+
+    <div id="documentation">
+
+      <h2 id="collections">Collection Functions (Arrays or Objects)</h2>
+
+      <p id="each">
+        <b class="header">each</b><code>_.each(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>forEach</b></span>
+        <br />
+        Iterates over a <b>list</b> of elements, yielding each in turn to an <b>iterator</b>
+        function. The <b>iterator</b> is bound to the <b>context</b> object, if one is
+        passed. Each invocation of <b>iterator</b> is called with three arguments:
+        <tt>(element, index, list)</tt>. If <b>list</b> is a JavaScript object, <b>iterator</b>'s
+        arguments will be <tt>(value, key, list)</tt>. Delegates to the native
+        <b>forEach</b> function if it exists.
+      </p>
+      <pre>
+_.each([1, 2, 3], function(num){ alert(num); });
+=&gt; alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
+=&gt; alerts each number in turn...</pre>
+
+      <p id="map">
+        <b class="header">map</b><code>_.map(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>collect</b></span>
+        <br />
+        Produces a new array of values by mapping each value in <b>list</b>
+        through a transformation function (<b>iterator</b>). If the native <b>map</b> method
+        exists, it will be used instead. If <b>list</b> is a JavaScript object,
+        <b>iterator</b>'s arguments will be <tt>(value, key, list)</tt>.
+      </p>
+      <pre>
+_.map([1, 2, 3], function(num){ return num * 3; });
+=&gt; [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=&gt; [3, 6, 9]</pre>
+
+      <p id="reduce">
+        <b class="header">reduce</b><code>_.reduce(list, iterator, memo, [context])</code>
+        <span class="alias">Aliases: <b>inject, foldl</b></span>
+        <br />
+        Also known as <b>inject</b> and <b>foldl</b>, <b>reduce</b> boils down a
+        <b>list</b> of values into a single value. <b>Memo</b> is the initial state
+        of the reduction, and each successive step of it should be returned by
+        <b>iterator</b>.
+      </p>
+      <pre>
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=&gt; 6
+</pre>
+
+      <p id="reduceRight">
+        <b class="header">reduceRight</b><code>_.reduceRight(list, iterator, memo, [context])</code>
+        <span class="alias">Alias: <b>foldr</b></span>
+        <br />
+        The right-associative version of <b>reduce</b>. Delegates to the
+        JavaScript 1.8 version of <b>reduceRight</b>, if it exists. <b>Foldr</b>
+        is not as useful in JavaScript as it would be in a language with lazy
+        evaluation.
+      </p>
+      <pre>
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=&gt; [4, 5, 2, 3, 0, 1]
+</pre>
+
+      <p id="find">
+        <b class="header">find</b><code>_.find(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>detect</b></span>
+        <br />
+        Looks through each value in the <b>list</b>, returning the first one that
+        passes a truth test (<b>iterator</b>). The function returns as
+        soon as it finds an acceptable element, and doesn't traverse the
+        entire list.
+      </p>
+      <pre>
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; 2
+</pre>
+
+      <p id="filter">
+        <b class="header">filter</b><code>_.filter(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>select</b></span>
+        <br />
+        Looks through each value in the <b>list</b>, returning an array of all
+        the values that pass a truth test (<b>iterator</b>). Delegates to the
+        native <b>filter</b> method, if it exists.
+      </p>
+      <pre>
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; [2, 4, 6]
+</pre>
+
+      <p id="reject">
+        <b class="header">reject</b><code>_.reject(list, iterator, [context])</code>
+        <br />
+        Returns the values in <b>list</b> without the elements that the truth
+        test (<b>iterator</b>) passes. The opposite of <b>filter</b>.
+      </p>
+      <pre>
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; [1, 3, 5]
+</pre>
+
+      <p id="all">
+        <b class="header">all</b><code>_.all(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>every</b></span>
+        <br />
+        Returns <i>true</i> if all of the values in the <b>list</b> pass the <b>iterator</b>
+        truth test. Delegates to the native method <b>every</b>, if present.
+      </p>
+      <pre>
+_.all([true, 1, null, 'yes'], _.identity);
+=&gt; false
+</pre>
+
+      <p id="any">
+        <b class="header">any</b><code>_.any(list, [iterator], [context])</code>
+        <span class="alias">Alias: <b>some</b></span>
+        <br />
+        Returns <i>true</i> if any of the values in the <b>list</b> pass the
+        <b>iterator</b> truth test. Short-circuits and stops traversing the list
+        if a true element is found. Delegates to the native method <b>some</b>,
+        if present.
+      </p>
+      <pre>
+_.any([null, 0, 'yes', false]);
+=&gt; true
+</pre>
+
+      <p id="include">
+        <b class="header">include</b><code>_.include(list, value)</code>
+        <span class="alias">Alias: <b>contains</b></span>
+        <br />
+        Returns <i>true</i> if the <b>value</b> is present in the <b>list</b>, using
+        <i>===</i> to test equality. Uses <b>indexOf</b> internally, if <b>list</b>
+        is an Array.
+      </p>
+      <pre>
+_.include([1, 2, 3], 3);
+=&gt; true
+</pre>
+
+      <p id="invoke">
+        <b class="header">invoke</b><code>_.invoke(list, methodName, [*arguments])</code>
+        <br />
+        Calls the method named by <b>methodName</b> on each value in the <b>list</b>.
+        Any extra arguments passed to <b>invoke</b> will be forwarded on to the
+        method invocation.
+      </p>
+      <pre>
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=&gt; [[1, 5, 7], [1, 2, 3]]
+</pre>
+
+      <p id="pluck">
+        <b class="header">pluck</b><code>_.pluck(list, propertyName)</code>
+        <br />
+        A convenient version of what is perhaps the most common use-case for
+        <b>map</b>: extracting a list of property values.
+      </p>
+      <pre>
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=&gt; ["moe", "larry", "curly"]
+</pre>
+
+      <p id="max">
+        <b class="header">max</b><code>_.max(list, [iterator], [context])</code>
+        <br />
+        Returns the maximum value in <b>list</b>. If <b>iterator</b> is passed,
+        it will be used on each value to generate the criterion by which the
+        value is ranked.
+      </p>
+      <pre>
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=&gt; {name : 'curly', age : 60};
+</pre>
+
+      <p id="min">
+        <b class="header">min</b><code>_.min(list, [iterator], [context])</code>
+        <br />
+        Returns the minimum value in <b>list</b>. If <b>iterator</b> is passed,
+        it will be used on each value to generate the criterion by which the
+        value is ranked.
+      </p>
+      <pre>
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=&gt; 2
+</pre>
+
+      <p id="sortBy">
+        <b class="header">sortBy</b><code>_.sortBy(list, iterator, [context])</code>
+        <br />
+        Returns a sorted copy of <b>list</b>, ranked in ascending order by the 
+        results of running each value through <b>iterator</b>.
+      </p>
+      <pre>
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=&gt; [5, 4, 6, 3, 1, 2]
+</pre>
+
+      <p id="groupBy">
+        <b class="header">groupBy</b><code>_.groupBy(list, iterator)</code>
+        <br />
+        Splits a collection into sets, grouped by the result of running each
+        value through <b>iterator</b>. If <b>iterator</b> is a string instead of
+        a function, groups by the property named by <b>iterator</b> on each of
+        the values.
+      </p>
+      <pre>
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=&gt; {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=&gt; {3: ["one", "two"], 5: ["three"]}
+</pre>
+
+      <p id="sortedIndex">
+        <b class="header">sortedIndex</b><code>_.sortedIndex(list, value, [iterator])</code>
+        <br />
+        Uses a binary search to determine the index at which the <b>value</b>
+        <i>should</i> be inserted into the <b>list</b> in order to maintain the <b>list</b>'s
+        sorted order. If an <b>iterator</b> is passed, it will be used to compute
+        the sort ranking of each value.
+      </p>
+      <pre>
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=&gt; 3
+</pre>
+
+      <p id="shuffle">
+        <b class="header">shuffle</b><code>_.shuffle(list)</code>
+        <br />
+        Returns a shuffled copy of the <b>list</b>, using a version of the 
+        <a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle</a>.
+      </p>
+      <pre>
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=&gt; [4, 1, 6, 3, 5, 2]
+</pre>
+
+      <p id="toArray">
+        <b class="header">toArray</b><code>_.toArray(list)</code>
+        <br />
+        Converts the <b>list</b> (anything that can be iterated over), into a
+        real Array. Useful for transmuting the <b>arguments</b> object.
+      </p>
+      <pre>
+(function(){ return _.toArray(arguments).slice(0); })(1, 2, 3);
+=&gt; [1, 2, 3]
+</pre>
+
+      <p id="size">
+        <b class="header">size</b><code>_.size(list)</code>
+        <br />
+        Return the number of values in the <b>list</b>.
+      </p>
+      <pre>
+_.size({one : 1, two : 2, three : 3});
+=&gt; 3
+</pre>
+
+      <h2 id="arrays">Array Functions</h2>
+
+      <p>
+        <i>Note: All array functions will also work on the <b>arguments</b> object.</i>
+      </p>
+
+      <p id="first">
+        <b class="header">first</b><code>_.first(array, [n])</code>
+        <span class="alias">Alias: <b>head</b></span>
+        <br />
+        Returns the first element of an <b>array</b>. Passing <b>n</b> will
+        return the first <b>n</b> elements of the array.
+      </p>
+      <pre>
+_.first([5, 4, 3, 2, 1]);
+=&gt; 5
+</pre>
+
+      <p id="initial">
+        <b class="header">initial</b><code>_.initial(array, [n])</code>
+        <br />
+        Returns everything but the last entry of the array. Especially useful on
+        the arguments object. Pass <b>n</b> to exclude the last <b>n</b> elements
+        from the result.
+      </p>
+      <pre>
+_.initial([5, 4, 3, 2, 1]);
+=&gt; [5, 4, 3, 2]
+</pre>
+
+      <p id="last">
+        <b class="header">last</b><code>_.last(array, [n])</code>
+        <br />
+        Returns the last element of an <b>array</b>. Passing <b>n</b> will return
+        the last <b>n</b> elements of the array.
+      </p>
+      <pre>
+_.last([5, 4, 3, 2, 1]);
+=&gt; 1
+</pre>
+
+      <p id="rest">
+        <b class="header">rest</b><code>_.rest(array, [index])</code>
+        <span class="alias">Alias: <b>tail</b></span>
+        <br />
+        Returns the <b>rest</b> of the elements in an array. Pass an <b>index</b>
+        to return the values of the array from that index onward.
+      </p>
+      <pre>
+_.rest([5, 4, 3, 2, 1]);
+=&gt; [4, 3, 2, 1]
+</pre>
+
+      <p id="compact">
+        <b class="header">compact</b><code>_.compact(array)</code>
+        <br />
+        Returns a copy of the <b>array</b> with all falsy values removed.
+        In JavaScript, <i>false</i>, <i>null</i>, <i>0</i>, <i>""</i>,
+        <i>undefined</i> and <i>NaN</i> are all falsy.
+      </p>
+      <pre>
+_.compact([0, 1, false, 2, '', 3]);
+=&gt; [1, 2, 3]
+</pre>
+
+      <p id="flatten">
+        <b class="header">flatten</b><code>_.flatten(array, [shallow])</code>
+        <br />
+        Flattens a nested <b>array</b> (the nesting can be to any depth). If you
+        pass <b>shallow</b>, the array will only be flattened a single level.
+      </p>
+      <pre>
+_.flatten([1, [2], [3, [[4]]]]);
+=&gt; [1, 2, 3, 4];
+
+_.flatten([1, [2], [3, [[4]]]], true);
+=&gt; [1, 2, 3, [[4]]];
+</pre>
+
+      <p id="without">
+        <b class="header">without</b><code>_.without(array, [*values])</code>
+        <br />
+        Returns a copy of the <b>array</b> with all instances of the <b>values</b>
+        removed. <i>===</i> is used for the equality test.
+      </p>
+      <pre>
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=&gt; [2, 3, 4]
+</pre>
+
+      <p id="union">
+        <b class="header">union</b><code>_.union(*arrays)</code>
+        <br />
+        Computes the union of the passed-in <b>arrays</b>: the list of unique items,
+        in order, that are present in one or more of the <b>arrays</b>.
+      </p>
+      <pre>
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=&gt; [1, 2, 3, 101, 10]
+</pre>
+
+      <p id="intersection">
+        <b class="header">intersection</b><code>_.intersection(*arrays)</code>
+        <br />
+        Computes the list of values that are the intersection of all the <b>arrays</b>.
+        Each value in the result is present in each of the <b>arrays</b>.
+      </p>
+      <pre>
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=&gt; [1, 2]
+</pre>
+
+      <p id="difference">
+        <b class="header">difference</b><code>_.difference(array, *others)</code>
+        <br />
+        Similar to <b>without</b>, but returns the values from <b>array</b> that
+        are not present in the <b>other</b> arrays.
+      </p>
+      <pre>
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=&gt; [1, 3, 4]
+</pre>
+
+      <p id="uniq">
+        <b class="header">uniq</b><code>_.uniq(array, [isSorted], [iterator])</code>
+        <span class="alias">Alias: <b>unique</b></span>
+        <br />
+        Produces a duplicate-free version of the <b>array</b>, using <i>===</i> to test
+        object equality. If you know in advance that the <b>array</b> is sorted,
+        passing <i>true</i> for <b>isSorted</b> will run a much faster algorithm.
+        If you want to compute unique items based on a transformation, pass an
+        <b>iterator</b> function.
+      </p>
+      <pre>
+_.uniq([1, 2, 1, 3, 1, 4]);
+=&gt; [1, 2, 3, 4]
+</pre>
+
+      <p id="zip">
+        <b class="header">zip</b><code>_.zip(*arrays)</code>
+        <br />
+        Merges together the values of each of the <b>arrays</b> with the
+        values at the corresponding position. Useful when you have separate
+        data sources that are coordinated through matching array indexes.
+        If you're working with a matrix of nested arrays, <b>zip.apply</b>
+        can transpose the matrix in a similar fashion.
+      </p>
+      <pre>
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=&gt; [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+</pre>
+
+      <p id="indexOf">
+        <b class="header">indexOf</b><code>_.indexOf(array, value, [isSorted])</code>
+        <br />
+        Returns the index at which <b>value</b> can be found in the <b>array</b>,
+        or <i>-1</i> if value is not present in the <b>array</b>. Uses the native
+        <b>indexOf</b> function unless it's missing. If you're working with a 
+        large array, and you know that the array is already sorted, pass <tt>true</tt>
+        for <b>isSorted</b> to use a faster binary search.
+      </p>
+      <pre>
+_.indexOf([1, 2, 3], 2);
+=&gt; 1
+</pre>
+
+      <p id="lastIndexOf">
+        <b class="header">lastIndexOf</b><code>_.lastIndexOf(array, value)</code>
+        <br />
+        Returns the index of the last occurrence of <b>value</b> in the <b>array</b>,
+        or <i>-1</i> if value is not present. Uses the native <b>lastIndexOf</b>
+        function if possible.
+      </p>
+      <pre>
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=&gt; 4
+</pre>
+
+      <p id="range">
+        <b class="header">range</b><code>_.range([start], stop, [step])</code>
+        <br />
+        A function to create flexibly-numbered lists of integers, handy for
+        <tt>each</tt> and <tt>map</tt> loops. <b>start</b>, if omitted, defaults
+        to <i>0</i>; <b>step</b> defaults to <i>1</i>. Returns a list of integers
+        from <b>start</b> to <b>stop</b>, incremented (or decremented) by <b>step</b>,
+        exclusive.
+      </p>
+      <pre>
+_.range(10);
+=&gt; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=&gt; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=&gt; [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=&gt; [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=&gt; []
+</pre>
+
+      <h2 id="functions">Function (uh, ahem) Functions</h2>
+
+      <p id="bind">
+        <b class="header">bind</b><code>_.bind(function, object, [*arguments])</code>
+        <br />
+        Bind a <b>function</b> to an <b>object</b>, meaning that whenever
+        the function is called, the value of <i>this</i> will be the <b>object</b>.
+        Optionally, bind <b>arguments</b> to the <b>function</b> to pre-fill them,
+        also known as <b>partial application</b>.
+      </p>
+      <pre>
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=&gt; 'hi: moe'
+</pre>
+
+      <p id="bindAll">
+        <b class="header">bindAll</b><code>_.bindAll(object, [*methodNames])</code>
+        <br />
+        Binds a number of methods on the <b>object</b>, specified by
+        <b>methodNames</b>, to be run in the context of that object whenever they
+        are invoked. Very handy for binding functions that are going to be used
+        as event handlers, which would otherwise be invoked with a fairly useless
+        <i>this</i>. If no <b>methodNames</b> are provided, all of the object's
+        function properties will be bound to it.
+      </p>
+      <pre>
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=&gt; When the button is clicked, this.label will have the correct value...
+</pre>
+
+      <p id="memoize">
+        <b class="header">memoize</b><code>_.memoize(function, [hashFunction])</code>
+        <br />
+        Memoizes a given <b>function</b> by caching the computed result. Useful
+        for speeding up slow-running computations. If passed an optional 
+        <b>hashFunction</b>, it will be used to compute the hash key for storing
+        the result, based on the arguments to the original function. The default
+        <b>hashFunction</b> just uses the first argument to the memoized function
+        as the key.
+      </p>
+      <pre>
+var fibonacci = _.memoize(function(n) {
+  return n &lt; 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+</pre>
+
+      <p id="delay">
+        <b class="header">delay</b><code>_.delay(function, wait, [*arguments])</code>
+        <br />
+        Much like <b>setTimeout</b>, invokes <b>function</b> after <b>wait</b>
+        milliseconds. If you pass the optional <b>arguments</b>, they will be
+        forwarded on to the <b>function</b> when it is invoked.
+      </p>
+      <pre>
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=&gt; 'logged later' // Appears after one second.
+</pre>
+
+      <p id="defer">
+        <b class="header">defer</b><code>_.defer(function)</code>
+        <br />
+        Defers invoking the <b>function</b> until the current call stack has cleared,
+        similar to using <b>setTimeout</b> with a delay of 0. Useful for performing
+        expensive computations or HTML rendering in chunks without blocking the UI thread
+        from updating.
+      </p>
+      <pre>
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+</pre>
+
+      <p id="throttle">
+        <b class="header">throttle</b><code>_.throttle(function, wait)</code>
+        <br />
+        Creates and returns a new, throttled version of the passed function, 
+        that, when invoked repeatedly, will only actually call the original function 
+        at most once per every <b>wait</b>
+        milliseconds. Useful for rate-limiting events that occur faster than you
+        can keep up with.
+      </p>
+      <pre>
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+</pre>
+
+      <p id="debounce">
+        <b class="header">debounce</b><code>_.debounce(function, wait)</code>
+        <br />
+        Creates and returns a new debounced version of the passed function that
+        will postpone its execution until after 
+        <b>wait</b> milliseconds have elapsed since the last time it  
+        was invoked. Useful for implementing behavior that should only happen 
+        <i>after</i> the input has stopped arriving. For example: rendering a 
+        preview of a Markdown comment, recalculating a layout after the window 
+        has stopped being resized, and so on.
+      </p>
+      <pre>
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+</pre>
+
+      <p id="once">
+        <b class="header">once</b><code>_.once(function)</code>
+        <br />
+        Creates a version of the function that can only be called one time. 
+        Repeated calls to the modified function will have no effect, returning
+        the value from the original call. Useful for initialization functions,
+        instead of having to set a boolean flag and then check it later.
+      </p>
+      <pre>
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+</pre>
+
+      <p id="after">
+        <b class="header">after</b><code>_.after(count, function)</code>
+        <br />
+        Creates a version of the function that will only be run after first 
+        being called <b>count</b> times. Useful for grouping asynchronous responses,
+        where you want to be sure that all the async calls have finished, before
+        proceeding.
+      </p>
+      <pre>
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes}); 
+});
+// renderNotes is run once, after all notes have saved.
+</pre>
+
+      <p id="wrap">
+        <b class="header">wrap</b><code>_.wrap(function, wrapper)</code>
+        <br />
+        Wraps the first <b>function</b> inside of the <b>wrapper</b> function,
+        passing it as the first argument. This allows the <b>wrapper</b> to
+        execute code before and after the <b>function</b> runs, adjust the arguments,
+        and execute it conditionally.
+      </p>
+      <pre>
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=&gt; 'before, hello: moe, after'
+</pre>
+
+      <p id="compose">
+        <b class="header">compose</b><code>_.compose(*functions)</code>
+        <br />
+        Returns the composition of a list of <b>functions</b>, where each function
+        consumes the return value of the function that follows. In math terms,
+        composing the functions <i>f()</i>, <i>g()</i>, and <i>h()</i> produces
+        <i>f(g(h()))</i>.
+      </p>
+      <pre>
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=&gt; 'hi: moe!'
+</pre>
+
+      <h2 id="objects">Object Functions</h2>
+
+      <p id="keys">
+        <b class="header">keys</b><code>_.keys(object)</code>
+        <br />
+        Retrieve all the names of the <b>object</b>'s properties.
+      </p>
+      <pre>
+_.keys({one : 1, two : 2, three : 3});
+=&gt; ["one", "two", "three"]
+</pre>
+
+      <p id="values">
+        <b class="header">values</b><code>_.values(object)</code>
+        <br />
+        Return all of the values of the <b>object</b>'s properties.
+      </p>
+      <pre>
+_.values({one : 1, two : 2, three : 3});
+=&gt; [1, 2, 3]
+</pre>
+
+      <p id="functions">
+        <b class="header">functions</b><code>_.functions(object)</code>
+        <span class="alias">Alias: <b>methods</b></span>
+        <br />
+        Returns a sorted list of the names of every method in an object &mdash;
+        that is to say, the name of every function property of the object.
+      </p>
+      <pre>
+_.functions(_);
+=&gt; ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+</pre>
+
+      <p id="extend">
+        <b class="header">extend</b><code>_.extend(destination, *sources)</code>
+        <br />
+        Copy all of the properties in the <b>source</b> objects over to the
+        <b>destination</b> object. It's in-order, so the last source will override
+        properties of the same name in previous arguments.
+      </p>
+      <pre>
+_.extend({name : 'moe'}, {age : 50});
+=&gt; {name : 'moe', age : 50}
+</pre>
+
+      <p id="defaults">
+        <b class="header">defaults</b><code>_.defaults(object, *defaults)</code>
+        <br />
+        Fill in missing properties in <b>object</b> with default values from the
+        <b>defaults</b> objects. As soon as the property is filled, further defaults
+        will have no effect.
+      </p>
+      <pre>
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=&gt; {flavor : "chocolate", sprinkles : "lots"}
+</pre>
+
+      <p id="clone">
+        <b class="header">clone</b><code>_.clone(object)</code>
+        <br />
+        Create a shallow-copied clone of the <b>object</b>. Any nested objects
+        or arrays will be copied by reference, not duplicated.
+      </p>
+      <pre>
+_.clone({name : 'moe'});
+=&gt; {name : 'moe'};
+</pre>
+
+      <p id="tap">
+        <b class="header">tap</b><code>_.tap(object, interceptor)</code>
+        <br />
+        Invokes <b>interceptor</b> with the <b>object</b>, and then returns <b>object</b>.
+        The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+      </p>
+      <pre>
+_.chain([1,2,3,200])
+  .filter(function(num) { return num % 2 == 0; })
+  .tap(console.log)
+  .map(function(num) { return num * num })
+  .value();
+=&gt; [2, 200]
+=&gt; [4, 40000]
+</pre>
+
+      <p id="has">
+        <b class="header">has</b><code>_.has(object, key)</code>
+        <br />
+        Does the object contain the given key? Identical to 
+        <tt>object.hasOwnProperty(key)</tt>, but uses a safe reference to the
+        <tt>hasOwnProperty</tt> function, in case it's been 
+        <a href="http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/">overridden accidentally</a>.
+      </p>
+      <pre>
+_.has({a: 1, b: 2, c: 3}, "b");
+=&gt; true
+</pre>
+
+      <p id="isEqual">
+        <b class="header">isEqual</b><code>_.isEqual(object, other)</code>
+        <br />
+        Performs an optimized deep comparison between the two objects, to determine
+        if they should be considered equal.
+      </p>
+      <pre>
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=&gt; false
+_.isEqual(moe, clone);
+=&gt; true
+</pre>
+
+      <p id="isEmpty">
+        <b class="header">isEmpty</b><code>_.isEmpty(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> contains no values.
+      </p>
+      <pre>
+_.isEmpty([1, 2, 3]);
+=&gt; false
+_.isEmpty({});
+=&gt; true
+</pre>
+
+      <p id="isElement">
+        <b class="header">isElement</b><code>_.isElement(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a DOM element.
+      </p>
+      <pre>
+_.isElement(jQuery('body')[0]);
+=&gt; true
+</pre>
+
+      <p id="isArray">
+        <b class="header">isArray</b><code>_.isArray(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is an Array.
+      </p>
+      <pre>
+(function(){ return _.isArray(arguments); })();
+=&gt; false
+_.isArray([1,2,3]);
+=&gt; true
+</pre>
+
+      <p id="isArguments">
+        <b class="header">isArguments</b><code>_.isArguments(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is an Arguments object.
+      </p>
+      <pre>
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=&gt; true
+_.isArguments([1,2,3]);
+=&gt; false
+</pre>
+
+      <p id="isFunction">
+        <b class="header">isFunction</b><code>_.isFunction(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Function.
+      </p>
+      <pre>
+_.isFunction(alert);
+=&gt; true
+</pre>
+
+      <p id="isString">
+        <b class="header">isString</b><code>_.isString(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a String.
+      </p>
+      <pre>
+_.isString("moe");
+=&gt; true
+</pre>
+
+      <p id="isNumber">
+        <b class="header">isNumber</b><code>_.isNumber(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Number (including <tt>NaN</tt>).
+      </p>
+      <pre>
+_.isNumber(8.4 * 5);
+=&gt; true
+</pre>
+
+      <p id="isBoolean">
+        <b class="header">isBoolean</b><code>_.isBoolean(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is either <i>true</i> or <i>false</i>.
+      </p>
+      <pre>
+_.isBoolean(null);
+=&gt; false
+</pre>
+
+      <p id="isDate">
+        <b class="header">isDate</b><code>_.isDate(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Date.
+      </p>
+      <pre>
+_.isDate(new Date());
+=&gt; true
+</pre>
+
+      <p id="isRegExp">
+        <b class="header">isRegExp</b><code>_.isRegExp(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a RegExp.
+      </p>
+      <pre>
+_.isRegExp(/moe/);
+=&gt; true
+</pre>
+
+      <p id="isNaN">
+        <b class="header">isNaN</b><code>_.isNaN(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is <i>NaN</i>.<br /> Note: this is not
+        the same as the native <b>isNaN</b> function, which will also return
+        true if the variable is <i>undefined</i>.
+      </p>
+      <pre>
+_.isNaN(NaN);
+=&gt; true
+isNaN(undefined);
+=&gt; true
+_.isNaN(undefined);
+=&gt; false
+</pre>
+
+      <p id="isNull">
+        <b class="header">isNull</b><code>_.isNull(object)</code>
+        <br />
+        Returns <i>true</i> if the value of <b>object</b> is <i>null</i>.
+      </p>
+      <pre>
+_.isNull(null);
+=&gt; true
+_.isNull(undefined);
+=&gt; false
+</pre>
+
+      <p id="isUndefined">
+        <b class="header">isUndefined</b><code>_.isUndefined(variable)</code>
+        <br />
+        Returns <i>true</i> if <b>variable</b> is <i>undefined</i>.
+      </p>
+      <pre>
+_.isUndefined(window.missingVariable);
+=&gt; true
+</pre>
+
+      <h2 id="utility">Utility Functions</h2>
+
+      <p id="noConflict">
+        <b class="header">noConflict</b><code>_.noConflict()</code>
+        <br />
+        Give control of the "_" variable back to its previous owner. Returns
+        a reference to the <b>Underscore</b> object.
+      </p>
+      <pre>
+var underscore = _.noConflict();</pre>
+
+      <p id="identity">
+        <b class="header">identity</b><code>_.identity(value)</code>
+        <br />
+        Returns the same value that is used as the argument. In math:
+        <tt>f(x) = x</tt><br />
+        This function looks useless, but is used throughout Underscore as
+        a default iterator.
+      </p>
+      <pre>
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=&gt; true</pre>
+
+      <p id="times">
+        <b class="header">times</b><code>_.times(n, iterator)</code>
+        <br />
+        Invokes the given iterator function <b>n</b> times.
+      </p>
+      <pre>
+_(3).times(function(){ genie.grantWish(); });</pre>
+
+      <p id="mixin">
+        <b class="header">mixin</b><code>_.mixin(object)</code>
+        <br />
+        Allows you to extend Underscore with your own utility functions. Pass
+        a hash of <tt>{name: function}</tt> definitions to have your functions 
+        added to the Underscore object, as well as the OOP wrapper.
+      </p>
+      <pre>
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=&gt; "Fabio"
+</pre>
+
+      <p id="uniqueId">
+        <b class="header">uniqueId</b><code>_.uniqueId([prefix])</code>
+        <br />
+        Generate a globally-unique id for client-side models or DOM elements
+        that need one. If <b>prefix</b> is passed, the id will be appended to it.
+      </p>
+      <pre>
+_.uniqueId('contact_');
+=&gt; 'contact_104'</pre>
+
+      <p id="escape">
+        <b class="header">escape</b><code>_.escape(string)</code>
+        <br />
+        Escapes a string for insertion into HTML, replacing 
+        <tt>&amp;</tt>, <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>&quot;</tt>, <tt>&#x27;</tt>, and <tt>&#x2F;</tt> characters.
+      </p>
+      <pre>
+_.escape('Curly, Larry &amp; Moe');
+=&gt; "Curly, Larry &amp;amp; Moe"</pre>
+
+      <p id="template">
+        <b class="header">template</b><code>_.template(templateString, [context])</code>
+        <br />
+        Compiles JavaScript templates into functions that can be evaluated
+        for rendering. Useful for rendering complicated bits of HTML from JSON
+        data sources. Template functions can both interpolate variables, using<br />
+        <tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with
+        <tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have
+        it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a
+        <b>context</b> object that has properties corresponding to the template's free
+        variables. If you're writing a one-off, you can pass the <b>context</b>
+        object as the second parameter to <b>template</b> in order to render
+        immediately instead of returning a template function.
+      </p>
+      <pre>
+var compiled = _.template("hello: &lt;%= name %&gt;");
+compiled({name : 'moe'});
+=&gt; "hello: moe"
+
+var list = "&lt;% _.each(people, function(name) { %&gt; &lt;li&gt;&lt;%= name %&gt;&lt;/li&gt; &lt;% }); %&gt;";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=&gt; "&lt;li&gt;moe&lt;/li&gt;&lt;li&gt;curly&lt;/li&gt;&lt;li&gt;larry&lt;/li&gt;"
+
+var template = _.template("&lt;b&gt;&lt;%- value %&gt;&lt;/b&gt;");
+template({value : '&lt;script&gt;'});
+=&gt; "&lt;b&gt;&amp;lt;script&amp;gt;&lt;/b&gt;"</pre>
+
+      <p>
+        You can also use <tt>print</tt> from within JavaScript code.  This is
+        sometimes more convenient than using <tt>&lt;%= ... %&gt;</tt>.
+      </p>
+      
+      <pre>
+var compiled = _.template("&lt;% print('Hello ' + epithet); %&gt;");
+compiled({epithet: "stooge"});
+=&gt; "Hello stooge."</pre>
+
+      <p>
+        If ERB-style delimiters aren't your cup of tea, you can change Underscore's
+        template settings to use different symbols to set off interpolated code.
+        Define an <b>interpolate</b> regex to match expressions that should be 
+        interpolated verbatim, an <b>escape</b> regex to match expressions that should 
+        be inserted after being HTML escaped, and an <b>evaluate</b> regex to match
+        expressions that should be evaluated without insertion into the resulting
+        string. You may define or omit any combination of the three.
+        For example, to perform
+        <a href="http://github.com/janl/mustache.js#readme">Mustache.js</a>
+        style templating:
+      </p>
+
+      <pre>
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=&gt; "Hello Mustache!"</pre>
+
+
+      <h2 id="chaining">Chaining</h2>
+
+      <p>
+        You can use Underscore in either an object-oriented or a functional style,
+        depending on your preference. The following two lines of code are
+        identical ways to double a list of numbers.
+      </p>
+
+    <pre>
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });</pre>
+
+      <p>
+        Using the object-oriented style allows you to chain together methods. Calling
+        <tt>chain</tt> on a wrapped object will cause all future method calls to
+        return wrapped objects as well. When you've finished the computation,
+        use <tt>value</tt> to retrieve the final value. Here's an example of chaining
+        together a <b>map/flatten/reduce</b>, in order to get the word count of
+        every word in a song.
+      </p>
+
+<pre>
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_.chain(lyrics)
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+}, {}).value();
+
+=&gt; {lumberjack : 2, all : 4, night : 2 ... }</pre>
+
+      <p>
+        In addition, the
+        <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/prototype">Array prototype's methods</a>
+        are proxied through the chained Underscore object, so you can slip a
+        <tt>reverse</tt> or a <tt>push</tt> into your chain, and continue to
+        modify the array.
+      </p>
+
+      <p id="chain">
+        <b class="header">chain</b><code>_.chain(obj)</code>
+        <br />
+        Returns a wrapped object. Calling methods on this object will continue
+        to return wrapped objects until <tt>value</tt> is used.
+      </p>
+      <pre>
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _.chain(stooges)
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=&gt; "moe is 21"
+</pre>
+
+      <p id="value">
+        <b class="header">value</b><code>_(obj).value()</code>
+        <br />
+        Extracts the value of a wrapped object.
+      </p>
+      <pre>
+_([1, 2, 3]).value();
+=&gt; [1, 2, 3]
+</pre>
+
+      <h2 id="links">Links &amp; Suggested Reading</h2>
+
+      <p>
+        <a href="http://mirven.github.com/underscore.lua/">Underscore.lua</a>,
+        a Lua port of the functions that are applicable in both languages.
+        Includes OOP-wrapping and chaining.
+        The <a href="http://github.com/mirven/underscore.lua">source</a> is
+        available on GitHub.
+      </p>
+      
+      <p>
+        <a href="http://brianhaveri.github.com/Underscore.php/">Underscore.php</a>,
+        a PHP port of the functions that are applicable in both languages.
+        Includes OOP-wrapping and chaining.
+        The <a href="http://github.com/brianhaveri/Underscore.php">source</a> is
+        available on GitHub.
+      </p>
+      
+      <p>
+        <a href="http://vti.github.com/underscore-perl/">Underscore-perl</a>,
+        a Perl port of many of the Underscore.js functions, 
+        aimed at on Perl hashes and arrays, also 
+        <a href="https://github.com/vti/underscore-perl/">available on GitHub</a>.
+      </p>
+      
+      <p>
+        <a href="https://github.com/edtsech/underscore.string">Underscore.string</a>,
+        an Underscore extension that adds functions for string-manipulation: 
+        <tt>trim</tt>, <tt>startsWith</tt>, <tt>contains</tt>, <tt>capitalize</tt>,
+        <tt>reverse</tt>, <tt>sprintf</tt>, and more.
+      </p>
+
+      <p>
+        Ruby's <a href="http://ruby-doc.org/core/classes/Enumerable.html">Enumerable</a> module.
+      </p>
+
+      <p>
+        <a href="http://www.prototypejs.org/">Prototype.js</a>, which provides
+        JavaScript with collection functions in the manner closest to Ruby's Enumerable.
+      </p>
+
+      <p>
+        Oliver Steele's
+        <a href="http://osteele.com/sources/javascript/functional/">Functional JavaScript</a>,
+        which includes comprehensive higher-order function support as well as string lambdas.
+      </p>
+      
+      <p>
+        Michael Aufreiter's <a href="http://substance.io/#michael/data-js">Data.js</a>,
+        a data manipulation + persistence library for JavaScript.
+      </p>
+
+      <p>
+        Python's <a href="http://docs.python.org/library/itertools.html">itertools</a>.
+      </p>
+
+      <h2 id="changelog">Change Log</h2>
+      
+      <p>
+        <b class="header">1.3.1</b> &mdash; <small><i>Jan. 23, 2012</i></small><br />
+        <ul>
+          <li>
+            Added an <tt>_.has</tt> function, as a safer way to use <tt>hasOwnProperty</tt>.
+          </li>
+          <li>
+            Added <tt>_.collect</tt> as an alias for <tt>_.map</tt>. Smalltalkers, rejoice.
+          </li>
+          <li>
+            Reverted an old change so that <tt>_.extend</tt> will correctly copy 
+            over keys with undefined values again.
+          </li>
+          <li>
+            Bugfix to stop escaping slashes within interpolations in <tt>_.template</tt>.
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.3.0</b> &mdash; <small><i>Jan. 11, 2012</i></small><br />
+        <ul>
+          <li>
+            Removed AMD (RequireJS) support from Underscore. If you'd like to use
+            Underscore with RequireJS, you can load it as a normal script, wrap
+            or patch your copy, or download a forked version.
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.2.4</b> &mdash; <small><i>Jan. 4, 2012</i></small><br />
+        <ul>
+          <li>
+            You now can (and probably should) write <tt>_.chain(list)</tt> 
+            instead of <tt>_(list).chain()</tt>.
+          </li>
+          <li>
+            Fix for escaped characters in Underscore templates, and for supporting
+            customizations of <tt>_.templateSettings</tt> that only define one or
+            two of the required regexes.
+          </li>
+          <li>
+            Fix for passing an array as the first argument to an <tt>_.wrap</tt>'d function.
+          </li>
+          <li>
+            Improved compatibility with ClojureScript, which adds a <tt>call</tt>
+            function to <tt>String.prototype</tt>.
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.2.3</b> &mdash; <small><i>Dec. 7, 2011</i></small><br />
+        <ul>
+          <li>
+            Dynamic scope is now preserved for compiled <tt>_.template</tt> functions,
+            so you can use the value of <tt>this</tt> if you like.
+          </li>
+          <li>
+            Sparse array support of <tt>_.indexOf</tt>, <tt>_.lastIndexOf</tt>.
+          </li>
+          <li>
+            Both <tt>_.reduce</tt> and <tt>_.reduceRight</tt> can now be passed an
+            explicitly <tt>undefined</tt> value. (There's no reason why you'd 
+            want to do this.)
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.2.2</b> &mdash; <small><i>Nov. 14, 2011</i></small><br />
+        <ul>
+          <li>
+            Continued tweaks to <tt>_.isEqual</tt> semantics. Now JS primitives are
+            considered equivalent to their wrapped versions, and arrays are compared
+            by their numeric properties only <small>(#351)</small>.
+          </li>
+          <li>
+            <tt>_.escape</tt> no longer tries to be smart about not double-escaping
+            already-escaped HTML entities. Now it just escapes regardless <small>(#350)</small>.
+          </li>
+          <li>
+            In <tt>_.template</tt>, you may now leave semicolons out of evaluated
+            statements if you wish: <tt>&lt;% }) %&gt;</tt> <small>(#369)</small>.
+          </li>
+          <li>
+            <tt>_.after(callback, 0)</tt> will now trigger the callback immediately,
+            making "after" easier to use with asynchronous APIs <small>(#366)</small>. 
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.2.1</b> &mdash; <small><i>Oct. 24, 2011</i></small><br />
+        <ul>
+          <li>
+            Several important bug fixes for <tt>_.isEqual</tt>, which should now 
+            do better on mutated Arrays, and on non-Array objects with 
+            <tt>length</tt> properties. <small>(#329)</small>
+          </li>
+          <li>
+            <b>jrburke</b> contributed Underscore exporting for AMD module loaders,
+            and <b>tonylukasavage</b> for Appcelerator Titanium. 
+            <small>(#335, #338)</small>
+          </li>
+          <li>
+            You can now <tt>_.groupBy(list, 'property')</tt> as a shortcut for
+            grouping values by a particular common property.
+          </li>
+          <li>
+            <tt>_.throttle</tt>'d functions now fire immediately upon invocation, 
+            and are rate-limited thereafter <small>(#170, #266)</small>.
+          </li>
+          <li>
+            Most of the <tt>_.is[Type]</tt> checks no longer ducktype.
+          </li>
+          <li>
+            The <tt>_.bind</tt> function now also works on constructors, a-la
+            ES5 ... but you would never want to use <tt>_.bind</tt> on a 
+            constructor function.
+          </li>
+          <li>
+            <tt>_.clone</tt> no longer wraps non-object types in Objects.
+          </li>
+          <li>
+            <tt>_.find</tt> and <tt>_.filter</tt> are now the preferred names for
+            <tt>_.detect</tt> and <tt>_.select</tt>.
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.2.0</b> &mdash; <small><i>Oct. 5, 2011</i></small><br />
+        <ul>
+          <li>
+            The <tt>_.isEqual</tt> function now 
+            supports true deep equality comparisons, with checks for cyclic structures,
+            thanks to Kit Cambridge.
+          </li>
+          <li>
+            Underscore templates now support HTML escaping interpolations, using 
+            <tt>&lt;%- ... %&gt;</tt> syntax. 
+          </li>
+          <li>
+            Ryan Tenney contributed <tt>_.shuffle</tt>, which uses a modified 
+            Fisher-Yates to give you a shuffled copy of an array. 
+          </li>
+          <li>
+            <tt>_.uniq</tt> can now be passed an optional iterator, to determine by 
+            what criteria an object should be considered unique.
+          </li>
+          <li>
+            <tt>_.last</tt> now takes an optional argument which will return the last
+            N elements of the list.
+          </li>
+          <li>
+            A new <tt>_.initial</tt> function was added, as a mirror of <tt>_.rest</tt>,
+            which returns all the initial values of a list (except the last N). 
+          </li>
+        </ul>
+      </p>
+      
+      <p>
+        <b class="header">1.1.7</b> &mdash; <small><i>July 13, 2011</i></small><br />
+        Added <tt>_.groupBy</tt>, which aggregates a collection into groups of like items.
+        Added <tt>_.union</tt> and <tt>_.difference</tt>, to complement the 
+        (re-named) <tt>_.intersection</tt>.
+        Various improvements for support of sparse arrays.
+        <tt>_.toArray</tt> now returns a clone, if directly passed an array.
+        <tt>_.functions</tt> now also returns the names of functions that are present
+        in the prototype chain.
+      </p>
+            
+      <p>
+        <b class="header">1.1.6</b> &mdash; <small><i>April 18, 2011</i></small><br />
+        Added <tt>_.after</tt>, which will return a function that only runs after
+        first being called a specified number of times.
+        <tt>_.invoke</tt> can now take a direct function reference.
+        <tt>_.every</tt> now requires an iterator function to be passed, which
+        mirrors the ECMA5 API.
+        <tt>_.extend</tt> no longer copies keys when the value is undefined.
+        <tt>_.bind</tt> now errors when trying to bind an undefined value.
+      </p>
+      
+      <p>
+        <b class="header">1.1.5</b> &mdash; <small><i>Mar 20, 2011</i></small><br />
+        Added an <tt>_.defaults</tt> function, for use merging together JS objects
+        representing default options.
+        Added an <tt>_.once</tt> function, for manufacturing functions that should
+        only ever execute a single time.
+        <tt>_.bind</tt> now delegates to the native ECMAScript 5 version, 
+        where available.
+        <tt>_.keys</tt> now throws an error when used on non-Object values, as in
+        ECMAScript 5.
+        Fixed a bug with <tt>_.keys</tt> when used over sparse arrays.
+      </p>
+      
+      <p>
+        <b class="header">1.1.4</b> &mdash; <small><i>Jan 9, 2011</i></small><br />
+        Improved compliance with ES5's Array methods when passing <tt>null</tt> 
+        as a value. <tt>_.wrap</tt> now correctly sets <tt>this</tt> for the
+        wrapped function. <tt>_.indexOf</tt> now takes an optional flag for
+        finding the insertion index in an array that is guaranteed to already
+        be sorted. Avoiding the use of <tt>.callee</tt>, to allow <tt>_.isArray</tt>
+        to work properly in ES5's strict mode.
+      </p>
+      
+      <p>
+        <b class="header">1.1.3</b> &mdash; <small><i>Dec 1, 2010</i></small><br />
+        In CommonJS, Underscore may now be required with just: <br />
+        <tt>var _ = require("underscore")</tt>.
+        Added <tt>_.throttle</tt> and <tt>_.debounce</tt> functions.
+        Removed <tt>_.breakLoop</tt>, in favor of an ECMA5-style un-<i>break</i>-able
+        each implementation &mdash; this removes the try/catch, and you'll now have
+        better stack traces for exceptions that are thrown within an Underscore iterator.
+        Improved the <b>isType</b> family of functions for better interoperability
+        with Internet Explorer host objects.
+        <tt>_.template</tt> now correctly escapes backslashes in templates.
+        Improved <tt>_.reduce</tt> compatibility with the ECMA5 version: 
+        if you don't pass an initial value, the first item in the collection is used.
+        <tt>_.each</tt> no longer returns the iterated collection, for improved
+        consistency with ES5's <tt>forEach</tt>.
+      </p>
+      
+      <p>
+        <b class="header">1.1.2</b><br />
+        Fixed <tt>_.contains</tt>, which was mistakenly pointing at 
+        <tt>_.intersect</tt> instead of <tt>_.include</tt>, like it should 
+        have been. Added <tt>_.unique</tt> as an alias for <tt>_.uniq</tt>.
+      </p>
+      
+      <p>
+        <b class="header">1.1.1</b><br />
+        Improved the speed of <tt>_.template</tt>, and its handling of multiline
+        interpolations. Ryan Tenney contributed optimizations to many Underscore 
+        functions. An annotated version of the source code is now available.
+      </p>
+      
+      <p>
+        <b class="header">1.1.0</b><br />
+        The method signature of <tt>_.reduce</tt> has been changed to match
+        the ECMAScript 5 signature, instead of the Ruby/Prototype.js version.
+        This is a backwards-incompatible change. <tt>_.template</tt> may now be
+        called with no arguments, and preserves whitespace. <tt>_.contains</tt>
+        is a new alias for <tt>_.include</tt>.
+      </p>
+      
+      <p>
+        <b class="header">1.0.4</b><br />
+        <a href="http://themoell.com/">Andri Möll</a> contributed the <tt>_.memoize</tt> 
+        function, which can be used to speed up expensive repeated computations 
+        by caching the results.
+      </p>
+      
+      <p>
+        <b class="header">1.0.3</b><br />
+        Patch that makes <tt>_.isEqual</tt> return <tt>false</tt> if any property
+        of the compared object has a <tt>NaN</tt> value. Technically the correct
+        thing to do, but of questionable semantics. Watch out for NaN comparisons.
+      </p>
+      
+      <p>
+        <b class="header">1.0.2</b><br />
+        Fixes <tt>_.isArguments</tt> in recent versions of Opera, which have
+        arguments objects as real Arrays.
+      </p>
+      
+      <p>
+        <b class="header">1.0.1</b><br />
+        Bugfix for <tt>_.isEqual</tt>, when comparing two objects with the same 
+        number of undefined keys, but with different names.
+      </p>
+      
+      <p>
+        <b class="header">1.0.0</b><br />
+        Things have been stable for many months now, so Underscore is now
+        considered to be out of beta, at <b>1.0</b>. Improvements since <b>0.6</b>
+        include <tt>_.isBoolean</tt>, and the ability to have <tt>_.extend</tt>
+        take multiple source objects.
+      </p>
+      
+      <p>
+        <b class="header">0.6.0</b><br />
+        Major release. Incorporates a number of 
+        <a href="http://github.com/ratbeard">Mile Frawley's</a> refactors for
+        safer duck-typing on collection functions, and cleaner internals. A new
+        <tt>_.mixin</tt> method that allows you to extend Underscore with utility
+        functions of your own. Added <tt>_.times</tt>, which works the same as in 
+        Ruby or Prototype.js. Native support for ECMAScript 5's <tt>Array.isArray</tt>, 
+        and <tt>Object.keys</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.5.8</b><br />
+        Fixed Underscore's collection functions to work on
+        <a href="https://developer.mozilla.org/En/DOM/NodeList">NodeLists</a> and
+        <a href="https://developer.mozilla.org/En/DOM/HTMLCollection">HTMLCollections</a>
+        once more, thanks to
+        <a href="http://github.com/jmtulloss">Justin Tulloss</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.7</b><br />
+        A safer implementation of <tt>_.isArguments</tt>, and a
+        faster <tt>_.isNumber</tt>,<br />thanks to
+        <a href="http://jedschmidt.com/">Jed Schmidt</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.6</b><br />
+        Customizable delimiters for <tt>_.template</tt>, contributed by
+        <a href="http://github.com/iamnoah">Noah Sloan</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.5</b><br />
+        Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.
+      </p>
+
+      <p>
+        <b class="header">0.5.4</b><br />
+        Fix for multiple single quotes within a template string for
+        <tt>_.template</tt>. See:
+        <a href="http://www.west-wind.com/Weblog/posts/509108.aspx">Rick Strahl's blog post</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.2</b><br />
+        New implementations of <tt>isArray</tt>, <tt>isDate</tt>, <tt>isFunction</tt>,
+        <tt>isNumber</tt>, <tt>isRegExp</tt>, and <tt>isString</tt>, thanks to
+        a suggestion from
+        <a href="http://www.broofa.com/">Robert Kieffer</a>.
+        Instead of doing <tt>Object#toString</tt>
+        comparisons, they now check for expected properties, which is less safe,
+        but more than an order of magnitude faster. Most other Underscore
+        functions saw minor speed improvements as a result.
+        <a href="http://dolzhenko.org/">Evgeniy Dolzhenko</a>
+        contributed <tt>_.tap</tt>,
+        <a href="http://ruby-doc.org/core-1.9/classes/Object.html#M000191">similar to Ruby 1.9's</a>,
+        which is handy for injecting side effects (like logging) into chained calls.
+      </p>
+
+      <p>
+        <b class="header">0.5.1</b><br />
+        Added an <tt>_.isArguments</tt> function. Lots of little safety checks
+        and optimizations contributed by
+        <a href="http://github.com/iamnoah/">Noah Sloan</a> and 
+        <a href="http://themoell.com/">Andri Möll</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.0</b><br />
+        <b>[API Changes]</b> <tt>_.bindAll</tt> now takes the context object as
+        its first parameter. If no method names are passed, all of the context
+        object's methods are bound to it, enabling chaining and easier binding.
+        <tt>_.functions</tt> now takes a single argument and returns the names
+        of its Function properties. Calling <tt>_.functions(_)</tt> will get you
+        the previous behavior.
+        Added <tt>_.isRegExp</tt> so that <tt>isEqual</tt> can now test for RegExp equality.
+        All of the "is" functions have been shrunk down into a single definition.
+        <a href="http://github.com/grayrest/">Karl Guertin</a> contributed patches.
+      </p>
+
+      <p>
+        <b class="header">0.4.7</b><br />
+        Added <tt>isDate</tt>, <tt>isNaN</tt>, and <tt>isNull</tt>, for completeness.
+        Optimizations for <tt>isEqual</tt> when checking equality between Arrays
+        or Dates. <tt>_.keys</tt> is now <small><i><b>25%&ndash;2X</b></i></small> faster (depending on your
+        browser) which speeds up the functions that rely on it, such as <tt>_.each</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.4.6</b><br />
+        Added the <tt>range</tt> function, a port of the
+        <a href="http://docs.python.org/library/functions.html#range">Python
+        function of the same name</a>, for generating flexibly-numbered lists
+        of integers. Original patch contributed by
+        <a href="http://github.com/kylichuku">Kirill Ishanov</a>.
+      </p>
+
+      <p>
+        <b class="header">0.4.5</b><br />
+        Added <tt>rest</tt> for Arrays and arguments objects, and aliased
+        <tt>first</tt> as <tt>head</tt>, and <tt>rest</tt> as <tt>tail</tt>,
+        thanks to <a href="http://github.com/lukesutton/">Luke Sutton</a>'s patches.
+        Added tests ensuring that all Underscore Array functions also work on
+        <i>arguments</i> objects.
+      </p>
+
+      <p>
+        <b class="header">0.4.4</b><br />
+        Added <tt>isString</tt>, and <tt>isNumber</tt>, for consistency. Fixed
+        <tt>_.isEqual(NaN, NaN)</tt> to return <i>true</i> (which is debatable).
+      </p>
+
+      <p>
+        <b class="header">0.4.3</b><br />
+        Started using the native <tt>StopIteration</tt> object in browsers that support it.
+        Fixed Underscore setup for CommonJS environments.
+      </p>
+
+      <p>
+        <b class="header">0.4.2</b><br />
+        Renamed the unwrapping function to <tt>value</tt>, for clarity.
+      </p>
+
+      <p>
+        <b class="header">0.4.1</b><br />
+        Chained Underscore objects now support the Array prototype methods, so
+        that you can perform the full range of operations on a wrapped array
+        without having to break your chain. Added a <tt>breakLoop</tt> method
+        to <b>break</b> in the middle of any Underscore iteration. Added an
+        <tt>isEmpty</tt> function that works on arrays and objects.
+      </p>
+
+      <p>
+        <b class="header">0.4.0</b><br />
+        All Underscore functions can now be called in an object-oriented style,
+        like so: <tt>_([1, 2, 3]).map(...);</tt>. Original patch provided by
+        <a href="http://macournoyer.com/">Marc-André Cournoyer</a>.
+        Wrapped objects can be chained through multiple
+        method invocations. A <a href="#functions"><tt>functions</tt></a> method
+        was added, providing a sorted list of all the functions in Underscore.
+      </p>
+
+      <p>
+        <b class="header">0.3.3</b><br />
+        Added the JavaScript 1.8 function <tt>reduceRight</tt>. Aliased it
+        as <tt>foldr</tt>, and aliased <tt>reduce</tt> as <tt>foldl</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.3.2</b><br />
+        Now runs on stock <a href="http://www.mozilla.org/rhino/">Rhino</a>
+        interpreters with: <tt>load("underscore.js")</tt>.
+        Added <a href="#identity"><tt>identity</tt></a> as a utility function.
+      </p>
+
+      <p>
+        <b class="header">0.3.1</b><br />
+        All iterators are now passed in the original collection as their third
+        argument, the same as JavaScript 1.6's <b>forEach</b>. Iterating over
+        objects is now called with <tt>(value, key, collection)</tt>, for details
+        see <a href="#each"><tt>_.each</tt></a>.
+      </p>
+
+      <p>
+        <b class="header">0.3.0</b><br />
+        Added <a href="http://github.com/dmitryBaranovskiy">Dmitry Baranovskiy</a>'s
+        comprehensive optimizations, merged in
+        <a href="http://github.com/kriskowal/">Kris Kowal</a>'s patches to make Underscore
+        <a href="http://wiki.commonjs.org/wiki/CommonJS">CommonJS</a> and
+        <a href="http://narwhaljs.org/">Narwhal</a> compliant.
+      </p>
+
+      <p>
+        <b class="header">0.2.0</b><br />
+        Added <tt>compose</tt> and <tt>lastIndexOf</tt>, renamed <tt>inject</tt> to
+        <tt>reduce</tt>, added aliases for <tt>inject</tt>, <tt>filter</tt>,
+        <tt>every</tt>, <tt>some</tt>, and <tt>forEach</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.1.1</b><br />
+        Added <tt>noConflict</tt>, so that the "Underscore" object can be assigned to
+        other variables.
+      </p>
+
+      <p>
+        <b class="header">0.1.0</b><br />
+        Initial release of Underscore.js.
+      </p>
+
+      <p>
+        <a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
+          <img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" />
+        </a>
+      </p>
+
+    </div>
+
+  </div>
+
+  <!-- Include Underscore, so you can play with it in the console. -->
+  <script type="text/javascript" src="underscore.js"></script>
+
+</body>
+</html>
diff --git a/weinre.server/node_modules/underscore/index.js b/weinre.server/node_modules/underscore/index.js
new file mode 100644
index 0000000..2cf0ca5
--- /dev/null
+++ b/weinre.server/node_modules/underscore/index.js
@@ -0,0 +1 @@
+module.exports = require('./underscore');
diff --git a/weinre.server/node_modules/underscore/raw/underscore.psd b/weinre.server/node_modules/underscore/raw/underscore.psd
new file mode 100644
index 0000000..73ad2d7
--- /dev/null
+++ b/weinre.server/node_modules/underscore/raw/underscore.psd
Binary files differ
diff --git a/weinre.server/node_modules/underscore/underscore-min.js b/weinre.server/node_modules/underscore/underscore-min.js
new file mode 100644
index 0000000..5b55f32
--- /dev/null
+++ b/weinre.server/node_modules/underscore/underscore-min.js
@@ -0,0 +1,31 @@
+// Underscore.js 1.3.1
+// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
+c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
+h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
+b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===n)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===n)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(x&&a.map===x)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==
+null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
+function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
+e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
+function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});
+return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){f==0?b[0]=a:(d=Math.floor(Math.random()*(f+1)),b[f]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
+c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=
+b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},[]);
+return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,
+d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(p&&a.indexOf===p)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(D&&a.lastIndexOf===D)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};
+var F=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));F.prototype=a.prototype;var b=new F,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,
+c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true:
+a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};
+b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
+1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
+b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
+b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.mixin=function(a){j(b.functions(a),
+function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
+u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
+function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
+true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
diff --git a/weinre.server/node_modules/underscore/underscore.js b/weinre.server/node_modules/underscore/underscore.js
new file mode 100644
index 0000000..208d4cd
--- /dev/null
+++ b/weinre.server/node_modules/underscore/underscore.js
@@ -0,0 +1,999 @@
+//     Underscore.js 1.3.1
+//     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+//     Underscore is freely distributable under the MIT license.
+//     Portions of Underscore are inspired or borrowed from Prototype,
+//     Oliver Steele's Functional, and John Resig's Micro-Templating.
+//     For all details and documentation:
+//     http://documentcloud.github.com/underscore
+
+(function() {
+
+  // Baseline setup
+  // --------------
+
+  // Establish the root object, `window` in the browser, or `global` on the server.
+  var root = this;
+
+  // Save the previous value of the `_` variable.
+  var previousUnderscore = root._;
+
+  // Establish the object that gets returned to break out of a loop iteration.
+  var breaker = {};
+
+  // Save bytes in the minified (but not gzipped) version:
+  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+  // Create quick reference variables for speed access to core prototypes.
+  var slice            = ArrayProto.slice,
+      unshift          = ArrayProto.unshift,
+      toString         = ObjProto.toString,
+      hasOwnProperty   = ObjProto.hasOwnProperty;
+
+  // All **ECMAScript 5** native function implementations that we hope to use
+  // are declared here.
+  var
+    nativeForEach      = ArrayProto.forEach,
+    nativeMap          = ArrayProto.map,
+    nativeReduce       = ArrayProto.reduce,
+    nativeReduceRight  = ArrayProto.reduceRight,
+    nativeFilter       = ArrayProto.filter,
+    nativeEvery        = ArrayProto.every,
+    nativeSome         = ArrayProto.some,
+    nativeIndexOf      = ArrayProto.indexOf,
+    nativeLastIndexOf  = ArrayProto.lastIndexOf,
+    nativeIsArray      = Array.isArray,
+    nativeKeys         = Object.keys,
+    nativeBind         = FuncProto.bind;
+
+  // Create a safe reference to the Underscore object for use below.
+  var _ = function(obj) { return new wrapper(obj); };
+
+  // Export the Underscore object for **Node.js**, with
+  // backwards-compatibility for the old `require()` API. If we're in
+  // the browser, add `_` as a global object via a string identifier,
+  // for Closure Compiler "advanced" mode.
+  if (typeof exports !== 'undefined') {
+    if (typeof module !== 'undefined' && module.exports) {
+      exports = module.exports = _;
+    }
+    exports._ = _;
+  } else {
+    root['_'] = _;
+  }
+
+  // Current version.
+  _.VERSION = '1.3.1';
+
+  // Collection Functions
+  // --------------------
+
+  // The cornerstone, an `each` implementation, aka `forEach`.
+  // Handles objects with the built-in `forEach`, arrays, and raw objects.
+  // Delegates to **ECMAScript 5**'s native `forEach` if available.
+  var each = _.each = _.forEach = function(obj, iterator, context) {
+    if (obj == null) return;
+    if (nativeForEach && obj.forEach === nativeForEach) {
+      obj.forEach(iterator, context);
+    } else if (obj.length === +obj.length) {
+      for (var i = 0, l = obj.length; i < l; i++) {
+        if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
+      }
+    } else {
+      for (var key in obj) {
+        if (_.has(obj, key)) {
+          if (iterator.call(context, obj[key], key, obj) === breaker) return;
+        }
+      }
+    }
+  };
+
+  // Return the results of applying the iterator to each element.
+  // Delegates to **ECMAScript 5**'s native `map` if available.
+  _.map = _.collect = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+    each(obj, function(value, index, list) {
+      results[results.length] = iterator.call(context, value, index, list);
+    });
+    if (obj.length === +obj.length) results.length = obj.length;
+    return results;
+  };
+
+  // **Reduce** builds up a single result from a list of values, aka `inject`,
+  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+    var initial = arguments.length > 2;
+    if (obj == null) obj = [];
+    if (nativeReduce && obj.reduce === nativeReduce) {
+      if (context) iterator = _.bind(iterator, context);
+      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+    }
+    each(obj, function(value, index, list) {
+      if (!initial) {
+        memo = value;
+        initial = true;
+      } else {
+        memo = iterator.call(context, memo, value, index, list);
+      }
+    });
+    if (!initial) throw new TypeError('Reduce of empty array with no initial value');
+    return memo;
+  };
+
+  // The right-associative version of reduce, also known as `foldr`.
+  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+    var initial = arguments.length > 2;
+    if (obj == null) obj = [];
+    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+      if (context) iterator = _.bind(iterator, context);
+      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+    }
+    var reversed = _.toArray(obj).reverse();
+    if (context && !initial) iterator = _.bind(iterator, context);
+    return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
+  };
+
+  // Return the first value which passes a truth test. Aliased as `detect`.
+  _.find = _.detect = function(obj, iterator, context) {
+    var result;
+    any(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) {
+        result = value;
+        return true;
+      }
+    });
+    return result;
+  };
+
+  // Return all the elements that pass a truth test.
+  // Delegates to **ECMAScript 5**'s native `filter` if available.
+  // Aliased as `select`.
+  _.filter = _.select = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+    each(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) results[results.length] = value;
+    });
+    return results;
+  };
+
+  // Return all the elements for which a truth test fails.
+  _.reject = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    each(obj, function(value, index, list) {
+      if (!iterator.call(context, value, index, list)) results[results.length] = value;
+    });
+    return results;
+  };
+
+  // Determine whether all of the elements match a truth test.
+  // Delegates to **ECMAScript 5**'s native `every` if available.
+  // Aliased as `all`.
+  _.every = _.all = function(obj, iterator, context) {
+    var result = true;
+    if (obj == null) return result;
+    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+    each(obj, function(value, index, list) {
+      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+    });
+    return result;
+  };
+
+  // Determine if at least one element in the object matches a truth test.
+  // Delegates to **ECMAScript 5**'s native `some` if available.
+  // Aliased as `any`.
+  var any = _.some = _.any = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
+    var result = false;
+    if (obj == null) return result;
+    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+    each(obj, function(value, index, list) {
+      if (result || (result = iterator.call(context, value, index, list))) return breaker;
+    });
+    return !!result;
+  };
+
+  // Determine if a given value is included in the array or object using `===`.
+  // Aliased as `contains`.
+  _.include = _.contains = function(obj, target) {
+    var found = false;
+    if (obj == null) return found;
+    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+    found = any(obj, function(value) {
+      return value === target;
+    });
+    return found;
+  };
+
+  // Invoke a method (with arguments) on every item in a collection.
+  _.invoke = function(obj, method) {
+    var args = slice.call(arguments, 2);
+    return _.map(obj, function(value) {
+      return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
+    });
+  };
+
+  // Convenience version of a common use case of `map`: fetching a property.
+  _.pluck = function(obj, key) {
+    return _.map(obj, function(value){ return value[key]; });
+  };
+
+  // Return the maximum element or (element-based computation).
+  _.max = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+    if (!iterator && _.isEmpty(obj)) return -Infinity;
+    var result = {computed : -Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed >= result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Return the minimum element (or element-based computation).
+  _.min = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+    if (!iterator && _.isEmpty(obj)) return Infinity;
+    var result = {computed : Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed < result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Shuffle an array.
+  _.shuffle = function(obj) {
+    var shuffled = [], rand;
+    each(obj, function(value, index, list) {
+      if (index == 0) {
+        shuffled[0] = value;
+      } else {
+        rand = Math.floor(Math.random() * (index + 1));
+        shuffled[index] = shuffled[rand];
+        shuffled[rand] = value;
+      }
+    });
+    return shuffled;
+  };
+
+  // Sort the object's values by a criterion produced by an iterator.
+  _.sortBy = function(obj, iterator, context) {
+    return _.pluck(_.map(obj, function(value, index, list) {
+      return {
+        value : value,
+        criteria : iterator.call(context, value, index, list)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }), 'value');
+  };
+
+  // Groups the object's values by a criterion. Pass either a string attribute
+  // to group by, or a function that returns the criterion.
+  _.groupBy = function(obj, val) {
+    var result = {};
+    var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+    each(obj, function(value, index) {
+      var key = iterator(value, index);
+      (result[key] || (result[key] = [])).push(value);
+    });
+    return result;
+  };
+
+  // Use a comparator function to figure out at what index an object should
+  // be inserted so as to maintain order. Uses binary search.
+  _.sortedIndex = function(array, obj, iterator) {
+    iterator || (iterator = _.identity);
+    var low = 0, high = array.length;
+    while (low < high) {
+      var mid = (low + high) >> 1;
+      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+    }
+    return low;
+  };
+
+  // Safely convert anything iterable into a real, live array.
+  _.toArray = function(iterable) {
+    if (!iterable)                return [];
+    if (iterable.toArray)         return iterable.toArray();
+    if (_.isArray(iterable))      return slice.call(iterable);
+    if (_.isArguments(iterable))  return slice.call(iterable);
+    return _.values(iterable);
+  };
+
+  // Return the number of elements in an object.
+  _.size = function(obj) {
+    return _.toArray(obj).length;
+  };
+
+  // Array Functions
+  // ---------------
+
+  // Get the first element of an array. Passing **n** will return the first N
+  // values in the array. Aliased as `head`. The **guard** check allows it to work
+  // with `_.map`.
+  _.first = _.head = function(array, n, guard) {
+    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+  };
+
+  // Returns everything but the last entry of the array. Especcialy useful on
+  // the arguments object. Passing **n** will return all the values in
+  // the array, excluding the last N. The **guard** check allows it to work with
+  // `_.map`.
+  _.initial = function(array, n, guard) {
+    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+  };
+
+  // Get the last element of an array. Passing **n** will return the last N
+  // values in the array. The **guard** check allows it to work with `_.map`.
+  _.last = function(array, n, guard) {
+    if ((n != null) && !guard) {
+      return slice.call(array, Math.max(array.length - n, 0));
+    } else {
+      return array[array.length - 1];
+    }
+  };
+
+  // Returns everything but the first entry of the array. Aliased as `tail`.
+  // Especially useful on the arguments object. Passing an **index** will return
+  // the rest of the values in the array from that index onward. The **guard**
+  // check allows it to work with `_.map`.
+  _.rest = _.tail = function(array, index, guard) {
+    return slice.call(array, (index == null) || guard ? 1 : index);
+  };
+
+  // Trim out all falsy values from an array.
+  _.compact = function(array) {
+    return _.filter(array, function(value){ return !!value; });
+  };
+
+  // Return a completely flattened version of an array.
+  _.flatten = function(array, shallow) {
+    return _.reduce(array, function(memo, value) {
+      if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+      memo[memo.length] = value;
+      return memo;
+    }, []);
+  };
+
+  // Return a version of the array that does not contain the specified value(s).
+  _.without = function(array) {
+    return _.difference(array, slice.call(arguments, 1));
+  };
+
+  // Produce a duplicate-free version of the array. If the array has already
+  // been sorted, you have the option of using a faster algorithm.
+  // Aliased as `unique`.
+  _.uniq = _.unique = function(array, isSorted, iterator) {
+    var initial = iterator ? _.map(array, iterator) : array;
+    var result = [];
+    _.reduce(initial, function(memo, el, i) {
+      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
+        memo[memo.length] = el;
+        result[result.length] = array[i];
+      }
+      return memo;
+    }, []);
+    return result;
+  };
+
+  // Produce an array that contains the union: each distinct element from all of
+  // the passed-in arrays.
+  _.union = function() {
+    return _.uniq(_.flatten(arguments, true));
+  };
+
+  // Produce an array that contains every item shared between all the
+  // passed-in arrays. (Aliased as "intersect" for back-compat.)
+  _.intersection = _.intersect = function(array) {
+    var rest = slice.call(arguments, 1);
+    return _.filter(_.uniq(array), function(item) {
+      return _.every(rest, function(other) {
+        return _.indexOf(other, item) >= 0;
+      });
+    });
+  };
+
+  // Take the difference between one array and a number of other arrays.
+  // Only the elements present in just the first array will remain.
+  _.difference = function(array) {
+    var rest = _.flatten(slice.call(arguments, 1));
+    return _.filter(array, function(value){ return !_.include(rest, value); });
+  };
+
+  // Zip together multiple lists into a single array -- elements that share
+  // an index go together.
+  _.zip = function() {
+    var args = slice.call(arguments);
+    var length = _.max(_.pluck(args, 'length'));
+    var results = new Array(length);
+    for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+    return results;
+  };
+
+  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+  // we need this function. Return the position of the first occurrence of an
+  // item in an array, or -1 if the item is not included in the array.
+  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+  // If the array is large and already in sort order, pass `true`
+  // for **isSorted** to use binary search.
+  _.indexOf = function(array, item, isSorted) {
+    if (array == null) return -1;
+    var i, l;
+    if (isSorted) {
+      i = _.sortedIndex(array, item);
+      return array[i] === item ? i : -1;
+    }
+    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+    for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
+    return -1;
+  };
+
+  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+  _.lastIndexOf = function(array, item) {
+    if (array == null) return -1;
+    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+    var i = array.length;
+    while (i--) if (i in array && array[i] === item) return i;
+    return -1;
+  };
+
+  // Generate an integer Array containing an arithmetic progression. A port of
+  // the native Python `range()` function. See
+  // [the Python documentation](http://docs.python.org/library/functions.html#range).
+  _.range = function(start, stop, step) {
+    if (arguments.length <= 1) {
+      stop = start || 0;
+      start = 0;
+    }
+    step = arguments[2] || 1;
+
+    var len = Math.max(Math.ceil((stop - start) / step), 0);
+    var idx = 0;
+    var range = new Array(len);
+
+    while(idx < len) {
+      range[idx++] = start;
+      start += step;
+    }
+
+    return range;
+  };
+
+  // Function (ahem) Functions
+  // ------------------
+
+  // Reusable constructor function for prototype setting.
+  var ctor = function(){};
+
+  // Create a function bound to a given object (assigning `this`, and arguments,
+  // optionally). Binding with arguments is also known as `curry`.
+  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
+  // We check for `func.bind` first, to fail fast when `func` is undefined.
+  _.bind = function bind(func, context) {
+    var bound, args;
+    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+    if (!_.isFunction(func)) throw new TypeError;
+    args = slice.call(arguments, 2);
+    return bound = function() {
+      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
+      ctor.prototype = func.prototype;
+      var self = new ctor;
+      var result = func.apply(self, args.concat(slice.call(arguments)));
+      if (Object(result) === result) return result;
+      return self;
+    };
+  };
+
+  // Bind all of an object's methods to that object. Useful for ensuring that
+  // all callbacks defined on an object belong to it.
+  _.bindAll = function(obj) {
+    var funcs = slice.call(arguments, 1);
+    if (funcs.length == 0) funcs = _.functions(obj);
+    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+    return obj;
+  };
+
+  // Memoize an expensive function by storing its results.
+  _.memoize = function(func, hasher) {
+    var memo = {};
+    hasher || (hasher = _.identity);
+    return function() {
+      var key = hasher.apply(this, arguments);
+      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+    };
+  };
+
+  // Delays a function for the given number of milliseconds, and then calls
+  // it with the arguments supplied.
+  _.delay = function(func, wait) {
+    var args = slice.call(arguments, 2);
+    return setTimeout(function(){ return func.apply(func, args); }, wait);
+  };
+
+  // Defers a function, scheduling it to run after the current call stack has
+  // cleared.
+  _.defer = function(func) {
+    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+  };
+
+  // Returns a function, that, when invoked, will only be triggered at most once
+  // during a given window of time.
+  _.throttle = function(func, wait) {
+    var context, args, timeout, throttling, more;
+    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
+    return function() {
+      context = this; args = arguments;
+      var later = function() {
+        timeout = null;
+        if (more) func.apply(context, args);
+        whenDone();
+      };
+      if (!timeout) timeout = setTimeout(later, wait);
+      if (throttling) {
+        more = true;
+      } else {
+        func.apply(context, args);
+      }
+      whenDone();
+      throttling = true;
+    };
+  };
+
+  // Returns a function, that, as long as it continues to be invoked, will not
+  // be triggered. The function will be called after it stops being called for
+  // N milliseconds.
+  _.debounce = function(func, wait) {
+    var timeout;
+    return function() {
+      var context = this, args = arguments;
+      var later = function() {
+        timeout = null;
+        func.apply(context, args);
+      };
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+    };
+  };
+
+  // Returns a function that will be executed at most one time, no matter how
+  // often you call it. Useful for lazy initialization.
+  _.once = function(func) {
+    var ran = false, memo;
+    return function() {
+      if (ran) return memo;
+      ran = true;
+      return memo = func.apply(this, arguments);
+    };
+  };
+
+  // Returns the first function passed as an argument to the second,
+  // allowing you to adjust arguments, run code before and after, and
+  // conditionally execute the original function.
+  _.wrap = function(func, wrapper) {
+    return function() {
+      var args = [func].concat(slice.call(arguments, 0));
+      return wrapper.apply(this, args);
+    };
+  };
+
+  // Returns a function that is the composition of a list of functions, each
+  // consuming the return value of the function that follows.
+  _.compose = function() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments;
+      for (var i = funcs.length - 1; i >= 0; i--) {
+        args = [funcs[i].apply(this, args)];
+      }
+      return args[0];
+    };
+  };
+
+  // Returns a function that will only be executed after being called N times.
+  _.after = function(times, func) {
+    if (times <= 0) return func();
+    return function() {
+      if (--times < 1) { return func.apply(this, arguments); }
+    };
+  };
+
+  // Object Functions
+  // ----------------
+
+  // Retrieve the names of an object's properties.
+  // Delegates to **ECMAScript 5**'s native `Object.keys`
+  _.keys = nativeKeys || function(obj) {
+    if (obj !== Object(obj)) throw new TypeError('Invalid object');
+    var keys = [];
+    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+    return keys;
+  };
+
+  // Retrieve the values of an object's properties.
+  _.values = function(obj) {
+    return _.map(obj, _.identity);
+  };
+
+  // Return a sorted list of the function names available on the object.
+  // Aliased as `methods`
+  _.functions = _.methods = function(obj) {
+    var names = [];
+    for (var key in obj) {
+      if (_.isFunction(obj[key])) names.push(key);
+    }
+    return names.sort();
+  };
+
+  // Extend a given object with all the properties in passed-in object(s).
+  _.extend = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      for (var prop in source) {
+        obj[prop] = source[prop];
+      }
+    });
+    return obj;
+  };
+
+  // Fill in a given object with default properties.
+  _.defaults = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      for (var prop in source) {
+        if (obj[prop] == null) obj[prop] = source[prop];
+      }
+    });
+    return obj;
+  };
+
+  // Create a (shallow-cloned) duplicate of an object.
+  _.clone = function(obj) {
+    if (!_.isObject(obj)) return obj;
+    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+  };
+
+  // Invokes interceptor with the obj, and then returns obj.
+  // The primary purpose of this method is to "tap into" a method chain, in
+  // order to perform operations on intermediate results within the chain.
+  _.tap = function(obj, interceptor) {
+    interceptor(obj);
+    return obj;
+  };
+
+  // Internal recursive comparison function.
+  function eq(a, b, stack) {
+    // Identical objects are equal. `0 === -0`, but they aren't identical.
+    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+    if (a === b) return a !== 0 || 1 / a == 1 / b;
+    // A strict comparison is necessary because `null == undefined`.
+    if (a == null || b == null) return a === b;
+    // Unwrap any wrapped objects.
+    if (a._chain) a = a._wrapped;
+    if (b._chain) b = b._wrapped;
+    // Invoke a custom `isEqual` method if one is provided.
+    if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
+    if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
+    // Compare `[[Class]]` names.
+    var className = toString.call(a);
+    if (className != toString.call(b)) return false;
+    switch (className) {
+      // Strings, numbers, dates, and booleans are compared by value.
+      case '[object String]':
+        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+        // equivalent to `new String("5")`.
+        return a == String(b);
+      case '[object Number]':
+        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+        // other numeric values.
+        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+      case '[object Date]':
+      case '[object Boolean]':
+        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+        // millisecond representations. Note that invalid dates with millisecond representations
+        // of `NaN` are not equivalent.
+        return +a == +b;
+      // RegExps are compared by their source patterns and flags.
+      case '[object RegExp]':
+        return a.source == b.source &&
+               a.global == b.global &&
+               a.multiline == b.multiline &&
+               a.ignoreCase == b.ignoreCase;
+    }
+    if (typeof a != 'object' || typeof b != 'object') return false;
+    // Assume equality for cyclic structures. The algorithm for detecting cyclic
+    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+    var length = stack.length;
+    while (length--) {
+      // Linear search. Performance is inversely proportional to the number of
+      // unique nested structures.
+      if (stack[length] == a) return true;
+    }
+    // Add the first object to the stack of traversed objects.
+    stack.push(a);
+    var size = 0, result = true;
+    // Recursively compare objects and arrays.
+    if (className == '[object Array]') {
+      // Compare array lengths to determine if a deep comparison is necessary.
+      size = a.length;
+      result = size == b.length;
+      if (result) {
+        // Deep compare the contents, ignoring non-numeric properties.
+        while (size--) {
+          // Ensure commutative equality for sparse arrays.
+          if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
+        }
+      }
+    } else {
+      // Objects with different constructors are not equivalent.
+      if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
+      // Deep compare objects.
+      for (var key in a) {
+        if (_.has(a, key)) {
+          // Count the expected number of properties.
+          size++;
+          // Deep compare each member.
+          if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
+        }
+      }
+      // Ensure that both objects contain the same number of properties.
+      if (result) {
+        for (key in b) {
+          if (_.has(b, key) && !(size--)) break;
+        }
+        result = !size;
+      }
+    }
+    // Remove the first object from the stack of traversed objects.
+    stack.pop();
+    return result;
+  }
+
+  // Perform a deep comparison to check if two objects are equal.
+  _.isEqual = function(a, b) {
+    return eq(a, b, []);
+  };
+
+  // Is a given array, string, or object empty?
+  // An "empty" object has no enumerable own-properties.
+  _.isEmpty = function(obj) {
+    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+    for (var key in obj) if (_.has(obj, key)) return false;
+    return true;
+  };
+
+  // Is a given value a DOM element?
+  _.isElement = function(obj) {
+    return !!(obj && obj.nodeType == 1);
+  };
+
+  // Is a given value an array?
+  // Delegates to ECMA5's native Array.isArray
+  _.isArray = nativeIsArray || function(obj) {
+    return toString.call(obj) == '[object Array]';
+  };
+
+  // Is a given variable an object?
+  _.isObject = function(obj) {
+    return obj === Object(obj);
+  };
+
+  // Is a given variable an arguments object?
+  _.isArguments = function(obj) {
+    return toString.call(obj) == '[object Arguments]';
+  };
+  if (!_.isArguments(arguments)) {
+    _.isArguments = function(obj) {
+      return !!(obj && _.has(obj, 'callee'));
+    };
+  }
+
+  // Is a given value a function?
+  _.isFunction = function(obj) {
+    return toString.call(obj) == '[object Function]';
+  };
+
+  // Is a given value a string?
+  _.isString = function(obj) {
+    return toString.call(obj) == '[object String]';
+  };
+
+  // Is a given value a number?
+  _.isNumber = function(obj) {
+    return toString.call(obj) == '[object Number]';
+  };
+
+  // Is the given value `NaN`?
+  _.isNaN = function(obj) {
+    // `NaN` is the only value for which `===` is not reflexive.
+    return obj !== obj;
+  };
+
+  // Is a given value a boolean?
+  _.isBoolean = function(obj) {
+    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+  };
+
+  // Is a given value a date?
+  _.isDate = function(obj) {
+    return toString.call(obj) == '[object Date]';
+  };
+
+  // Is the given value a regular expression?
+  _.isRegExp = function(obj) {
+    return toString.call(obj) == '[object RegExp]';
+  };
+
+  // Is a given value equal to null?
+  _.isNull = function(obj) {
+    return obj === null;
+  };
+
+  // Is a given variable undefined?
+  _.isUndefined = function(obj) {
+    return obj === void 0;
+  };
+
+  // Has own property?
+  _.has = function(obj, key) {
+    return hasOwnProperty.call(obj, key);
+  };
+
+  // Utility Functions
+  // -----------------
+
+  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+  // previous owner. Returns a reference to the Underscore object.
+  _.noConflict = function() {
+    root._ = previousUnderscore;
+    return this;
+  };
+
+  // Keep the identity function around for default iterators.
+  _.identity = function(value) {
+    return value;
+  };
+
+  // Run a function **n** times.
+  _.times = function (n, iterator, context) {
+    for (var i = 0; i < n; i++) iterator.call(context, i);
+  };
+
+  // Escape a string for HTML interpolation.
+  _.escape = function(string) {
+    return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
+  };
+
+  // Add your own custom functions to the Underscore object, ensuring that
+  // they're correctly added to the OOP wrapper as well.
+  _.mixin = function(obj) {
+    each(_.functions(obj), function(name){
+      addToWrapper(name, _[name] = obj[name]);
+    });
+  };
+
+  // Generate a unique integer id (unique within the entire client session).
+  // Useful for temporary DOM ids.
+  var idCounter = 0;
+  _.uniqueId = function(prefix) {
+    var id = idCounter++;
+    return prefix ? prefix + id : id;
+  };
+
+  // By default, Underscore uses ERB-style template delimiters, change the
+  // following template settings to use alternative delimiters.
+  _.templateSettings = {
+    evaluate    : /<%([\s\S]+?)%>/g,
+    interpolate : /<%=([\s\S]+?)%>/g,
+    escape      : /<%-([\s\S]+?)%>/g
+  };
+
+  // When customizing `templateSettings`, if you don't want to define an
+  // interpolation, evaluation or escaping regex, we need one that is
+  // guaranteed not to match.
+  var noMatch = /.^/;
+
+  // Within an interpolation, evaluation, or escaping, remove HTML escaping
+  // that had been previously added.
+  var unescape = function(code) {
+    return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
+  };
+
+  // JavaScript micro-templating, similar to John Resig's implementation.
+  // Underscore templating handles arbitrary delimiters, preserves whitespace,
+  // and correctly escapes quotes within interpolated code.
+  _.template = function(str, data) {
+    var c  = _.templateSettings;
+    var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+      'with(obj||{}){__p.push(\'' +
+      str.replace(/\\/g, '\\\\')
+         .replace(/'/g, "\\'")
+         .replace(c.escape || noMatch, function(match, code) {
+           return "',_.escape(" + unescape(code) + "),'";
+         })
+         .replace(c.interpolate || noMatch, function(match, code) {
+           return "'," + unescape(code) + ",'";
+         })
+         .replace(c.evaluate || noMatch, function(match, code) {
+           return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
+         })
+         .replace(/\r/g, '\\r')
+         .replace(/\n/g, '\\n')
+         .replace(/\t/g, '\\t')
+         + "');}return __p.join('');";
+    var func = new Function('obj', '_', tmpl);
+    if (data) return func(data, _);
+    return function(data) {
+      return func.call(this, data, _);
+    };
+  };
+
+  // Add a "chain" function, which will delegate to the wrapper.
+  _.chain = function(obj) {
+    return _(obj).chain();
+  };
+
+  // The OOP Wrapper
+  // ---------------
+
+  // If Underscore is called as a function, it returns a wrapped object that
+  // can be used OO-style. This wrapper holds altered versions of all the
+  // underscore functions. Wrapped objects may be chained.
+  var wrapper = function(obj) { this._wrapped = obj; };
+
+  // Expose `wrapper.prototype` as `_.prototype`
+  _.prototype = wrapper.prototype;
+
+  // Helper function to continue chaining intermediate results.
+  var result = function(obj, chain) {
+    return chain ? _(obj).chain() : obj;
+  };
+
+  // A method to easily add functions to the OOP wrapper.
+  var addToWrapper = function(name, func) {
+    wrapper.prototype[name] = function() {
+      var args = slice.call(arguments);
+      unshift.call(args, this._wrapped);
+      return result(func.apply(_, args), this._chain);
+    };
+  };
+
+  // Add all of the Underscore functions to the wrapper object.
+  _.mixin(_);
+
+  // Add all mutator Array functions to the wrapper.
+  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+    var method = ArrayProto[name];
+    wrapper.prototype[name] = function() {
+      var wrapped = this._wrapped;
+      method.apply(wrapped, arguments);
+      var length = wrapped.length;
+      if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
+      return result(wrapped, this._chain);
+    };
+  });
+
+  // Add all accessor Array functions to the wrapper.
+  each(['concat', 'join', 'slice'], function(name) {
+    var method = ArrayProto[name];
+    wrapper.prototype[name] = function() {
+      return result(method.apply(this._wrapped, arguments), this._chain);
+    };
+  });
+
+  // Start chaining a wrapped Underscore object.
+  wrapper.prototype.chain = function() {
+    this._chain = true;
+    return this;
+  };
+
+  // Extracts the result from a wrapped and chained object.
+  wrapper.prototype.value = function() {
+    return this._wrapped;
+  };
+
+}).call(this);
diff --git a/weinre.server/src/weinre/server/Channel.java b/weinre.server/src/weinre/server/Channel.java
deleted file mode 100644
index 6401e42..0000000
--- a/weinre.server/src/weinre/server/Channel.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-//-------------------------------------------------------------------
-public class Channel {
-
-    static public final String AnonymousId = "anonymous";
-
-    private String                pathPrefix;
-    private String                name;
-    private String                id;
-    private MessageQueue<String>  requestQueue;
-    private MessageQueue<String>  responseQueue;
-    private boolean               isClosed;
-    private Connector             connector;
-    private long                  lastRead;
-    private Map<String,Object>    serviceMap;
-    private String                remoteHost;
-    private String                remoteAddress;
-    private PrintWriter           messageLog;
-
-    //---------------------------------------------------------------
-    public Channel(String pathPrefix, String name, String id, String remoteHost, String remoteAddress) {
-        this.pathPrefix         = pathPrefix;
-        this.name               = name;
-        this.id                 = id;
-        this.remoteHost         = remoteHost;
-        this.remoteAddress      = remoteAddress;
-        this.requestQueue       = new MessageQueue<String>();
-        this.responseQueue      = new MessageQueue<String>();
-        this.isClosed           = false;
-        this.connector          = null;
-        this.serviceMap         = new HashMap<String,Object>();
-        this.lastRead           = System.currentTimeMillis();
-        this.messageLog         = Main.getSettings().getMessageLog();
-    }
-
-    //---------------------------------------------------------------
-    public Connector getConnector() {
-        return connector;
-    }
-
-    //---------------------------------------------------------------
-    public String getRemoteHost() {
-        return remoteHost;
-    }
-
-    //---------------------------------------------------------------
-    public String getRemoteAddress() {
-        return remoteAddress;
-    }
-
-    //---------------------------------------------------------------
-    protected void _setConnector(Connector connector) {
-        this.connector = connector;
-    }
-
-    //---------------------------------------------------------------
-    public void sendCallback(String intfName, String callbackId, Object... args) throws IOException {
-        if (callbackId == null) return;
-
-        List<Object> innerArgs = new ArrayList<Object>();
-        innerArgs.add(callbackId);
-        innerArgs.add(Arrays.asList(args));
-
-        sendEvent(intfName, "sendCallback", innerArgs.toArray());
-    }
-
-    //---------------------------------------------------------------
-    public void sendEvent(String intfName, String methodName, Object... args) {
-        Main.debug(getName() + ": send " + intfName + "." + methodName + "()");
-
-        JSONObject response = new JSONObject();
-
-        String responseString;
-        try {
-            response.put("interface", intfName);
-            response.put("method", methodName);
-
-            List<Object> passedArgs = new ArrayList<Object>(Arrays.asList(args));
-
-            response.put("args", passedArgs);
-
-            responseString = response.toString();
-        }
-        catch (JSONException e) {
-            Main.warn("IOException serializing message for " + intfName + "." + methodName);
-            return;
-        }
-
-        this.postResponse(responseString);
-    }
-
-    //---------------------------------------------------------------
-    public Object getService(String name) {
-        try {
-            return getService_(name);
-        }
-        catch (InstantiationException e) {
-            throw new RuntimeException(e);
-        }
-        catch (IllegalAccessException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings("rawtypes")
-    private Object getService_(String name) throws InstantiationException, IllegalAccessException {
-        if (serviceMap.containsKey(name)) return serviceMap.get(name);
-
-        String klassName = "weinre.server.service." + name;
-        Class  klass = null;
-        try {
-            klass = Class.forName(klassName);
-        }
-        catch (ClassNotFoundException e) {
-            // Main.debug("service class not found: " + klassName);
-            serviceMap.put(name, null);
-            return null;
-        }
-
-        Object result = klass.newInstance();
-        serviceMap.put(name, result);
-        // Main.debug("loaded service class: " + klassName);
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public void close() {
-        isClosed = true;
-        requestQueue.shutdown();
-        responseQueue.shutdown();
-
-        ChannelManager.$.deregisterChannel(name);
-    }
-
-    //---------------------------------------------------------------
-    public boolean isClosed() {
-        return isClosed;
-    }
-
-    //---------------------------------------------------------------
-    public String getPathPrefix() {
-        return pathPrefix;
-    }
-
-    //---------------------------------------------------------------
-    public String getName() {
-        return name;
-    }
-
-    //---------------------------------------------------------------
-    public String getId() {
-        return id;
-    }
-
-    //---------------------------------------------------------------
-    public long getLastRead() {
-        return lastRead;
-    }
-
-    //---------------------------------------------------------------
-    public void updateLastRead() {
-        lastRead = System.currentTimeMillis();
-    }
-
-    //---------------------------------------------------------------
-    public void postRequest(String json) {
-        if (isClosed()) return;
-
-        requestQueue.add(json);
-        log(json);
-    }
-
-    //---------------------------------------------------------------
-    public void postResponse(String json) {
-        if (isClosed()) return;
-
-        responseQueue.add(json);
-        log(json);
-    }
-
-    //---------------------------------------------------------------
-    private void log(String json) {
-        if (null == messageLog) return;
-
-        JSONObject jObject;
-        try {
-            jObject = new JSONObject(json);
-            jObject.put("_to", getName() + "#" + getId());
-        }
-        catch (JSONException e) {
-            return;
-        }
-
-        messageLog.print(jObject.toString(true));
-        messageLog.println(",");
-    }
-
-    //---------------------------------------------------------------
-    public List<String> getRequests(int timeoutSeconds) throws InterruptedException {
-        if (isClosed()) return new LinkedList<String>();
-
-        List<String> result = requestQueue.getAll(timeoutSeconds, TimeUnit.SECONDS);
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public List<String> getResponses(int timeoutSeconds) throws InterruptedException {
-        if (isClosed()) return new LinkedList<String>();
-
-        List<String> result = responseQueue.getAll(timeoutSeconds, TimeUnit.SECONDS);
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public String toString() {
-        return getClass().getName() + "{" + pathPrefix + ":" + name + "}";
-    }
-}
diff --git a/weinre.server/src/weinre/server/ChannelManager.java b/weinre.server/src/weinre/server/ChannelManager.java
deleted file mode 100644
index 2926b09..0000000
--- a/weinre.server/src/weinre/server/ChannelManager.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-//-------------------------------------------------------------------
-public class ChannelManager {
-
-    static final public ChannelManager $ = new ChannelManager();
-
-    private Map<String, Channel>              channelMap;
-    private List<ChannelManagerEventListener> eventListeners;
-
-    //---------------------------------------------------------------
-    private ChannelManager() {
-        super();
-
-        channelMap     = new HashMap<String, Channel>();
-        eventListeners = new ArrayList<ChannelManagerEventListener>();
-    }
-
-    //---------------------------------------------------------------
-    public void addEventListener(ChannelManagerEventListener listener) {
-        eventListeners.add(listener);
-    }
-
-    //---------------------------------------------------------------
-    public void removeEventListener(ChannelManagerEventListener listener) {
-        eventListeners.add(listener);
-    }
-
-    //---------------------------------------------------------------
-    private void fireRegisteredEvent(Channel channel) {
-        for (ChannelManagerEventListener listener: eventListeners) {
-            listener.channelRegistered(channel);
-        }
-    }
-
-    //---------------------------------------------------------------
-    private void fireDeregisteredEvent(Channel channel) {
-        for (ChannelManagerEventListener listener: eventListeners) {
-            listener.channelDeregistered(channel);
-        }
-    }
-
-    //---------------------------------------------------------------
-    public Channel getChannel(String channelName) {
-        return channelMap.get(channelName);
-    }
-
-    //---------------------------------------------------------------
-    public Channel getChannel(String channelName, String remoteAddress) {
-        Channel channel = getChannel(channelName);
-        if (null == channel) return null;
-
-        if (!channel.getRemoteAddress().equals(remoteAddress)) return null;
-
-        return channel;
-    }
-
-    //---------------------------------------------------------------
-    public List<Channel> getChannels() {
-        return new ArrayList<Channel>(channelMap.values());
-    }
-
-    //---------------------------------------------------------------
-    public Channel registerChannel(String pathPrefix, String channelName, String id, String remoteHost, String remoteAddress) {
-        if (channelMap.containsKey(channelName)) return null;
-
-        Channel channel = new Channel(pathPrefix, channelName, id, remoteHost, remoteAddress);
-        channelMap.put(channelName, channel);
-
-        fireRegisteredEvent(channel);
-
-        return channel;
-    }
-
-    //---------------------------------------------------------------
-    public Channel deregisterChannel(String channelName) {
-        Channel channel = getChannel(channelName);
-        if (null == channel) return null;
-
-        fireDeregisteredEvent(channel);
-
-        channelMap.remove(channelName);
-
-        return channel;
-    }
-
-}
-
diff --git a/weinre.server/src/weinre/server/ChannelManagerEventListener.java b/weinre.server/src/weinre/server/ChannelManagerEventListener.java
deleted file mode 100644
index f15f2dd..0000000
--- a/weinre.server/src/weinre/server/ChannelManagerEventListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-//-------------------------------------------------------------------
-public interface ChannelManagerEventListener {
-
-    //---------------------------------------------------------------
-    public void channelRegistered(Channel channel);
-
-    //---------------------------------------------------------------
-    public void channelDeregistered(Channel channel);
-}
diff --git a/weinre.server/src/weinre/server/Client.java b/weinre.server/src/weinre/server/Client.java
deleted file mode 100644
index d2118cc..0000000
--- a/weinre.server/src/weinre/server/Client.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import org.apache.wink.json4j.JSONArray;
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-//-------------------------------------------------------------------
-public class Client extends Connector {
-
-    private Target connectedTarget;
-
-    //---------------------------------------------------------------
-    public Client(Channel channel) {
-        super(channel);
-        _register();
-    }
-
-    //---------------------------------------------------------------
-    public boolean isClient() {
-        return true;
-    }
-
-    //---------------------------------------------------------------
-    public Target getConnectedTarget() {
-        return connectedTarget;
-    }
-
-    //---------------------------------------------------------------
-    protected void _connect(Target target) {
-        if (null == target) return;
-
-        Lock.lock();
-
-        try {
-            connectedTarget = target;
-        }
-        finally {
-            Lock.unlock();
-        }
-    }
-
-    //---------------------------------------------------------------
-    protected void _disconnect(Target target) {
-        if (null == target) return;
-
-        Lock.lock();
-
-        try {
-            connectedTarget = null;
-        }
-        finally {
-            Lock.unlock();
-        }
-    }
-
-    //---------------------------------------------------------------
-    public JSONObject getDescription() {
-      JSONObject result = new JSONObject();
-
-      try {
-          result.put("channel",            getChannel().getName());
-          result.put("id",                 getChannel().getId());
-          result.put("hostName",           getChannel().getRemoteHost());
-          result.put("connectedTargetIds", new JSONArray());
-      }
-      catch (JSONException e) {
-          throw new RuntimeException(e);
-      }
-
-      return result;
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/ConnectionManager.java b/weinre.server/src/weinre/server/ConnectionManager.java
deleted file mode 100644
index 88994cc..0000000
--- a/weinre.server/src/weinre/server/ConnectionManager.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-//-------------------------------------------------------------------
-public class ConnectionManager {
-
-    static final public ConnectionManager $ = new ConnectionManager();
-
-    private Map<String,Client> clientMap;
-    private Map<String,Target> targetMap;
-    private boolean            listening = false;
-
-    //---------------------------------------------------------------
-    private ConnectionManager() {
-        super();
-
-        clientMap = Collections.synchronizedMap(new HashMap<String,Client>());
-        targetMap = Collections.synchronizedMap(new HashMap<String,Target>());
-    }
-
-    //---------------------------------------------------------------
-    public void startChannelListener() {
-        if (listening) return;
-        listening = true;
-
-        ChannelManager.$.addEventListener(new ChannelManagerEventListener() {
-
-            @Override
-            public void channelRegistered(Channel channel) {
-            }
-
-            @Override
-            public void channelDeregistered(Channel channel) {
-                Connector connector = channel.getConnector();
-                if (null == connector) return;
-
-                if (connector.isClient()) ConnectionManager.$._closeClient((Client) connector);
-                if (connector.isTarget()) ConnectionManager.$._closeTarget((Target) connector);
-            }
-        });
-    }
-
-    //---------------------------------------------------------------
-    public void addClient(Client client) {
-        clientMap.put(client.getName(), client);
-        _sendAllClientsEvent("WeinreClientEvents", client.getId(), "clientRegistered", client.getDescription());
-    }
-
-    //---------------------------------------------------------------
-    public void addTarget(Target target) {
-        targetMap.put(target.getName(), target);
-        _sendAllClientsEvent("WeinreClientEvents", target.getId(), "targetRegistered", target.getDescription());
-    }
-
-    //---------------------------------------------------------------
-    private void _removeClient(Client client) {
-        _sendAllClientsEvent("WeinreClientEvents", client.getId(), "clientUnregistered", client.getName());
-        clientMap.remove(client.getName());
-    }
-
-    //---------------------------------------------------------------
-    private void _removeTarget(Target target) {
-        _sendAllClientsEvent("WeinreClientEvents", target.getId(), "targetUnregistered", target.getName());
-        targetMap.remove(target.getName());
-    }
-
-    //---------------------------------------------------------------
-    public Client getClient(String name) {
-        return clientMap.get(name);
-    }
-
-    //---------------------------------------------------------------
-    public Target getTarget(String name) {
-        return targetMap.get(name);
-    }
-
-    //---------------------------------------------------------------
-    public List<Client> getClients(String id) {
-        List<Client> result = new ArrayList<Client>();
-
-        for (Client client: clientMap.values()) {
-            if (client.getId().equals(id)) {
-                result.add(client);
-            }
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public List<Target> getTargets(String id) {
-        List<Target> result = new ArrayList<Target>();
-
-        for (Target target: targetMap.values()) {
-            if (target.getId().equals(id)) {
-                result.add(target);
-            }
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public void connect(Client client, Target target) {
-        if ((client == null) || (target == null)) return;
-
-        Target connectedTarget = client.getConnectedTarget();
-        if (connectedTarget == target) return;
-
-        disconnect(client, connectedTarget);
-
-        client._connect(target);
-        target._connect(client);
-
-        _sendConnectionCreatedEvent(client, target);
-    }
-
-    //---------------------------------------------------------------
-    public void disconnect(Client client, Target target) {
-        if ((client == null) || (target == null)) return;
-
-        client._disconnect(target);
-        target._disconnect(client);
-
-        _sendConnectionDestroyedEvent(client, target);
-    }
-
-    //---------------------------------------------------------------
-    private void _sendConnectionCreatedEvent(Client client, Target target) {
-        _sendConnectionEvent(client, target, "connectionCreated");
-    }
-
-    //---------------------------------------------------------------
-    private void _sendConnectionDestroyedEvent(Client client, Target target) {
-        _sendConnectionEvent(client, target, "connectionDestroyed");
-    }
-
-    //---------------------------------------------------------------
-    private void _sendConnectionEvent(Client client, Target target, String message) {
-        String clientName = client.getChannel().getName();
-        String targetName = target.getChannel().getName();
-
-        _sendAllClientsEvent("WeinreClientEvents", client.getId(), message, clientName, targetName);
-        target.getChannel().sendEvent("WeinreTargetEvents", message, clientName, targetName);
-    }
-
-    //---------------------------------------------------------------
-    private void _sendAllClientsEvent(String intfName, String id, String message, Object... args) {
-        for (Client aClient: getClients(id)) {
-            aClient.getChannel().sendEvent(intfName, message, args);
-        }
-    }
-
-    //---------------------------------------------------------------
-    protected void closeConnector(Connector connector) {
-        if (null == connector) return;
-
-        if (connector.isClient()) _closeClient((Client)connector);
-        if (connector.isTarget()) _closeTarget((Target)connector);
-    }
-
-    //---------------------------------------------------------------
-    private void _closeClient(Client client) {
-        if (null == client) return;
-
-        Target target = client.getConnectedTarget();
-        if (null != target) {
-            disconnect(client, target);
-        }
-
-        _removeClient(client);
-    }
-
-    //---------------------------------------------------------------
-    private void _closeTarget(Target target) {
-        if (null == target) return;
-
-        List<Client> clients = target.getConnectedClients();
-
-        for (Client client: clients) {
-            disconnect(client, target);
-        }
-
-        _removeTarget(target);
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/Connector.java b/weinre.server/src/weinre/server/Connector.java
deleted file mode 100644
index 5497895..0000000
--- a/weinre.server/src/weinre/server/Connector.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.apache.wink.json4j.JSONObject;
-
-//-------------------------------------------------------------------
-abstract public class Connector {
-
-    static final protected Lock Lock = new ReentrantLock();
-
-    private Channel channel;
-
-    //---------------------------------------------------------------
-    public Connector(Channel channel) {
-        super();
-
-        this.channel = channel;
-        channel._setConnector(this);
-    }
-
-    //---------------------------------------------------------------
-    protected void _register() {
-        if (isClient()) ConnectionManager.$.addClient((Client) this);
-        if (isTarget()) ConnectionManager.$.addTarget((Target) this);
-    }
-
-    //---------------------------------------------------------------
-    public Channel getChannel() {
-        return channel;
-    }
-
-    //---------------------------------------------------------------
-    public String getName() {
-        return channel.getName();
-    }
-
-    //---------------------------------------------------------------
-    public String getId() {
-        return channel.getId();
-    }
-
-    //---------------------------------------------------------------
-    public List<Connector> getConnections() {
-        List<Connector> result = new ArrayList<Connector>();
-
-        if (isClient()) {
-            Connector target = ((Client) this).getConnectedTarget();
-            if (null != target) {
-                result.add(target);
-            }
-        }
-
-        else if (isTarget()) {
-            result.addAll(((Target) this).getConnectedClients());
-        }
-
-        else {
-            throw new RuntimeException("connector which isn't a client or target");
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    abstract public JSONObject getDescription();
-
-    //---------------------------------------------------------------
-    public boolean isClosed() {
-        return channel.isClosed();
-    }
-
-    //---------------------------------------------------------------
-    public boolean isClient() {
-        return false;
-    }
-
-    //---------------------------------------------------------------
-    public boolean isTarget() {
-        return false;
-    }
-
-    //---------------------------------------------------------------
-    public String toString() {
-        return getClass().getName() + "{" + channel + "}";
-    }
-}
diff --git a/weinre.server/src/weinre/server/ConsoleOutputStream.java b/weinre.server/src/weinre/server/ConsoleOutputStream.java
deleted file mode 100644
index 307addc..0000000
--- a/weinre.server/src/weinre/server/ConsoleOutputStream.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-
-//-------------------------------------------------------------------
-public class ConsoleOutputStream extends OutputStream {
-
-    private Main                 main;
-    private PrintStream          originalStream;
-    private StringBuffer         stringBuffer;
-    private boolean              stdout;
-
-    //---------------------------------------------------------------
-    static public PrintStream newPrintStream(Main main, PrintStream originalStream, boolean stdout) {
-        return new PrintStream(new ConsoleOutputStream(main, originalStream, stdout));
-    }
-
-    //---------------------------------------------------------------
-    public ConsoleOutputStream(Main main, PrintStream originalStream, boolean stdout) {
-        this.main           = main;
-        this.originalStream = originalStream;
-        this.stdout         = stdout;
-        this.stringBuffer   = new StringBuffer();
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public void write(int c) throws IOException {
-        if (c == 0x0D) return;
-
-        if (c != 0x0A) {
-            stringBuffer.append(Character.toChars(c));
-            return;
-        }
-
-        String line = stringBuffer.toString();
-        stringBuffer = new StringBuffer();
-        _writeLine(line);
-    }
-
-    //---------------------------------------------------------------
-    private void _writeLine(String line) {
-        originalStream.println(line);
-
-        main.addServerConsoleMessage(line, stdout);
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/ExtensionManager.java b/weinre.server/src/weinre/server/ExtensionManager.java
deleted file mode 100644
index 6831904..0000000
--- a/weinre.server/src/weinre/server/ExtensionManager.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jetty.util.resource.Resource;
-
-//-------------------------------------------------------------------
-public class ExtensionManager {
-    static private File     weinreHomeDir = null;
-    static private File     weinreExtDir  = null;
-    static private long     weinreExtDate = 0L;
-    static private String[] extensions    = null;
-
-    static private String[] EMPTY_STRING_ARRAY = {};
-
-    //---------------------------------------------------------------
-    static {
-        initExtensions();
-    }
-
-    //---------------------------------------------------------------
-    static public String[] getExtensions() {
-        if (null == weinreExtDir) return extensions;
-
-        if (weinreExtDate != weinreExtDir.lastModified()) {
-            initExtensions();
-        }
-
-        return extensions;
-    }
-
-    //---------------------------------------------------------------
-    // path: /client/extensions/weinre-ext-sample/extension.html
-    static public Resource getResource(String path) throws MalformedURLException {
-        if (null == weinreExtDir) return null;
-
-        File resourceFile = new File(weinreExtDir, path.substring(18));
-        if (!resourceFile.exists()) return null;
-
-        try {
-            return Resource.newResource(resourceFile.toURI().toURL().toExternalForm(), false);
-        }
-        catch (IOException e) {
-            throw new MalformedURLException();
-        }
-    }
-
-    //---------------------------------------------------------------
-    static private void initExtensions() {
-
-        extensions = EMPTY_STRING_ARRAY;
-
-        weinreHomeDir = new File(System.getProperty("user.home"), ".weinre");
-        if (!weinreHomeDir.isDirectory()) {
-            Main.info("extensions not enabled: ~/.weinre is not a directory");
-            return;
-        }
-
-        weinreExtDir  = new File(weinreHomeDir, "extensions");
-        weinreExtDate = weinreExtDir.lastModified();
-        if (!weinreExtDir.isDirectory()) {
-            Main.info("extensions not enabled: ~/.weinre/extensions is not a directory");
-            return;
-        }
-
-        List<String> extensionList = new ArrayList<String>();
-
-        String[] entries = weinreExtDir.list();
-        for (String entry: entries) {
-            if (entry.startsWith(".")) continue;
-
-            File extDir = new File(weinreExtDir, entry);
-            if (!extDir.isDirectory()) continue;
-
-            File extensionHtml = new File(extDir, "extension.html");
-            if (!extensionHtml.isFile()) continue;
-
-            extensionList.add(entry);
-        }
-
-        extensions = extensionList.toArray(EMPTY_STRING_ARRAY);
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/Main.java b/weinre.server/src/weinre/server/Main.java
deleted file mode 100644
index c762142..0000000
--- a/weinre.server/src/weinre/server/Main.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.log.StdErrLog;
-
-import weinre.server.http.HttpServer;
-
-//-------------------------------------------------------------------
-public class Main {
-
-    private static ServerSettings  Settings;
-    private static Logger          Logger;
-
-    public  Server       server;
-    private PrintStream  consoleStdout;
-    private PrintStream  consoleStderr;
-
-    //---------------------------------------------------------------
-    static public void main(String[] args) throws Throwable {
-        Main main = new Main(args);
-
-        main.run();
-    }
-
-    //---------------------------------------------------------------
-    static public ServerSettings getSettings() {
-        return Settings;
-    }
-
-    //---------------------------------------------------------------
-    static public boolean isDebug() {
-        return Settings.getVerbose();
-    }
-
-    //---------------------------------------------------------------
-    static public void warn(  String message ) { Logger.warn(message);  }
-    static public void info(  String message ) { Logger.info(message);  }
-    static public void debug( String message ) { Logger.debug(message); }
-    static public void error( String message ) { Logger.warn(message);  }
-
-    //---------------------------------------------------------------
-    public Main(String[] args) {
-        super();
-
-        Settings = ServerSettings.getOptions(args);
-        if (null == Settings) System.exit(0);
-
-        if (null != Settings.getMessageLog()) {
-            Settings.getMessageLog().println("[");
-        }
-
-        Runtime.getRuntime().addShutdownHook(onShutdownThread());
-
-        consoleStdout = ConsoleOutputStream.newPrintStream(this, System.out, true);
-        consoleStderr = ConsoleOutputStream.newPrintStream(this, System.err, false);
-
-        System.setOut(consoleStdout);
-        System.setErr(consoleStderr);
-    }
-
-    //---------------------------------------------------------------
-    public void run() throws Throwable, Exception {
-        httpServerStart();
-        httpServerWaitTillDone();
-        exit();
-    }
-
-    //---------------------------------------------------------------
-    private Thread onShutdownThread() {
-        return new Thread(new Runnable() {
-            public void run() {
-                PrintWriter messageLog = Settings.getMessageLog();
-                if (null == messageLog) return;
-
-                messageLog.println("null ]");
-                messageLog.close();
-            }
-        });
-    }
-
-    //---------------------------------------------------------------
-    public int exit() {
-        if (null != server) {
-            try {
-                server.setGracefulShutdown(1000);
-                server.setStopAtShutdown(true);
-
-                for (org.eclipse.jetty.server.Connector connector: server.getConnectors()) {
-                    connector.stop();
-                    connector.close();
-                }
-                server.stop();
-            }
-            catch (Exception e) {
-                warn("exception stopping the server: " + e);
-                e.printStackTrace();
-            }
-        }
-
-        System.exit(0);
-        return 0;
-    }
-
-    //---------------------------------------------------------------
-    public void httpServerStart() {
-        // get the default logger - this should be the first thing to touch the log
-        Logger defaultLog = Log.getLog();
-
-        if (defaultLog instanceof StdErrLog) {
-            ((StdErrLog) defaultLog).setHideStacks(true);
-        }
-
-        // create a special logger for weinre messages
-        Logger = org.eclipse.jetty.util.log.Log.getLogger("weinre");
-        Logger.setDebugEnabled(Settings.getVerbose());
-
-        server = null;
-        try {
-            server = new HttpServer(this, Settings).run();
-        }
-        catch (Throwable e) {
-            severeError("exception launching server: " + e);
-        }
-
-        ConnectionManager.$.startChannelListener();
-        WatchDog.start();
-        MessageHandler.start();
-    }
-
-    //---------------------------------------------------------------
-    public void httpServerWaitTillDone() {
-        try {
-            server.join();
-        }
-        catch (Throwable e) {
-            severeError("exception waiting for server to stop: " + e);
-        }
-    }
-
-    //---------------------------------------------------------------
-    public void serverStarted() {
-    }
-
-    //---------------------------------------------------------------
-    public void addServerConsoleMessage(String line, boolean stdout) {
-    }
-
-    //---------------------------------------------------------------
-    public int severeError(String message) {
-        Logger.warn(message);
-        Logger.warn("exiting...");
-        return exit();
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/MessageHandler.java b/weinre.server/src/weinre/server/MessageHandler.java
deleted file mode 100644
index da878ba..0000000
--- a/weinre.server/src/weinre/server/MessageHandler.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.wink.json4j.JSONArray;
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-//-------------------------------------------------------------------
-public class MessageHandler {
-    private PrintWriter messageLog;
-
-    //---------------------------------------------------------------
-    static public void start() {
-        final MessageHandler messageHandler = new MessageHandler();
-
-        Runnable runnable = new Runnable() {
-            public void run() {
-                while (true) {
-                    try {
-                        messageHandler.handleMessages();
-                        Thread.sleep(250);
-                    }
-                    catch(InterruptedException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-        };
-
-        Thread thread = new Thread(runnable, messageHandler.getClass().toString());
-        thread.start();
-    }
-
-    //---------------------------------------------------------------
-    private MessageHandler() {
-        messageLog = Main.getSettings().getMessageLog();
-    }
-
-    //---------------------------------------------------------------
-    private void handleMessages() throws InterruptedException {
-        List<Channel> channels = ChannelManager.$.getChannels();
-
-        for (Channel channel: channels) {
-            List<String> requestss = channel.getRequests(0);
-
-            for (String requests: requestss) {
-                JSONArray acc;
-
-                try {
-                    acc = new JSONArray(requests);
-                }
-                catch (JSONException e) {
-                    Main.warn("error parsing requests: " + e + ": '" + requests + "'");
-                    continue;
-                }
-
-                int size = acc.length();
-                for (int i=0; i<size; i++) {
-                    JSONObject accRequest;
-                    String request = "???";
-                    try {
-                        request = acc.getString(i);
-                        accRequest = new JSONObject(request);
-                        accRequest.put("_from", channel.getName() + "#" + channel.getId());
-
-                        if (null != messageLog) {
-                            messageLog.print(accRequest.toString(true));
-                            messageLog.println(",");
-                        }
-
-                    }
-                    catch (JSONException e) {
-                        Main.warn("error parsing request: " + e + ": '" + request + "'");
-                        continue;
-                    }
-
-                    String intfName;
-                    String methodName;
-                    JSONArray args;
-                    try {
-                        intfName = accRequest.getString("interface");
-                        methodName = accRequest.getString("method");
-                        args       = accRequest.getJSONArray("args");
-                    } catch (JSONException e) {
-                        throw new RuntimeException(e);
-                    }
-
-                    if (null == intfName) {
-                        Main.warn("no interface specified in request: " + request);
-                        continue;
-                    }
-
-                    if (null == methodName) {
-                        Main.warn("no methodName specified in request: " + request);
-                        continue;
-                    }
-
-                    if (null == args) {
-                        Main.warn("no args specified in request: " + request);
-                        continue;
-                    }
-
-                    serviceMethodInvoker(channel, intfName, methodName, args);
-                }
-            }
-        }
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private void serviceMethodInvoker(Channel channel, String intfName, String methodName, JSONArray argsJSON) {
-        Object service;
-
-        String methodSignature = intfName + "." + methodName + "()";
-
-        if (Main.isDebug()) {
-            String methodSignatureParms = intfName + "." + methodName + "(" + argsJSON.toString() + ")";
-            Main.debug(channel.getName() + ": recv " + methodSignatureParms);
-        }
-
-        try {
-            service = channel.getService(intfName);
-        }
-        catch (RuntimeException e) {
-            Main.warn("unable to get service object for: " + methodSignature + "; " + e);
-            return;
-        }
-
-        if (null == service) {
-            redirectToConnections(channel, intfName, methodName, argsJSON);
-            return;
-        }
-
-        Class serviceClass = service.getClass();
-
-        List<Object> args = new ArrayList<Object>(argsJSON);
-
-        for (Method method: serviceClass.getMethods()) {
-            if (!method.getName().equals(methodName)) continue;
-
-            if (method.getParameterTypes().length != args.size() + 1) {
-                Main.warn("invalid number of parameters specified for : " + methodSignature);
-                return;
-            }
-
-            args.add(0, channel);
-
-            try {
-                method.invoke(service, args.toArray());
-            }
-            catch (IllegalArgumentException e) {
-                Main.warn("illegal argument exception invoking : " + methodSignature + "; " + e);
-            }
-            catch (IllegalAccessException e) {
-                Main.warn("illegal access exception invoking : " + methodSignature + "; " + e);
-            }
-            catch (InvocationTargetException e) {
-                Throwable te = e.getTargetException();
-                Main.warn("invocation target exception invoking : " + methodSignature + "; " + te);
-                te.printStackTrace();
-            }
-            catch (RuntimeException e) {
-                Main.warn("invocation runtime exception invoking : " + methodSignature + "; " + e);
-            }
-
-            return;
-        }
-
-        Main.warn("no method found to invoke for: " + methodSignature);
-    }
-
-    //---------------------------------------------------------------
-    private void redirectToConnections(Channel channel, String interfaceName, String methodName, JSONArray args) {
-        Connector connector = channel.getConnector();
-        if (null == connector) return;
-
-        List<Connector> connections = connector.getConnections();
-
-        for (Connector connection: connections) {
-            connection.getChannel().sendEvent(interfaceName, methodName, args.toArray());
-        }
-    }
-
-
-}
diff --git a/weinre.server/src/weinre/server/MessageQueue.java b/weinre.server/src/weinre/server/MessageQueue.java
deleted file mode 100644
index 3c464eb..0000000
--- a/weinre.server/src/weinre/server/MessageQueue.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A type of blocking queue.
- *
- * - can be shutdown; subsequent add() or getAll() calls throw ISE
- * - getAll() takes all items off the queue
- * - if there are simultaneous getAll() calls, queued items may be split between them
- * - current use case calls for one reader, so previous item not relevant
- */
-public class MessageQueue<E> {
-
-    private BlockingQueue<E> queue;
-    private boolean          closed;
-    private Object           closeLock;
-
-    //---------------------------------------------------------------
-    public MessageQueue() {
-        super();
-
-        queue     = new LinkedBlockingQueue<E>();
-        closed    = false;
-        closeLock = new Object();
-    }
-
-    //---------------------------------------------------------------
-    public void shutdown() {
-        synchronized(closeLock) {
-            if (closed) return;
-
-            closed = true;
-            queue.clear();
-        }
-    }
-
-    //---------------------------------------------------------------
-    public void add(E item) {
-        synchronized(closeLock) {
-            if (closed) throw new IllegalStateException("the blocking queue is closed");
-        }
-
-        queue.add(item);
-    }
-
-    //---------------------------------------------------------------
-    public List<E> getAll(int timeout, TimeUnit timeUnit) throws InterruptedException {
-        synchronized(closeLock) {
-            if (closed) throw new IllegalStateException("the blocking queue is closed");
-        }
-
-        // create our result list
-        List<E> result = new LinkedList<E>();
-
-        // wait for the first item
-        E item = queue.poll(timeout, timeUnit);
-
-        // nothing there?  return empty list
-        if (null == item) return result;
-
-        // add the first item to the list
-        result.add(item);
-
-        // get anything else on the queue
-        // - not appropriate for simultaneous calls to this method
-        while ((item = queue.poll()) != null) {
-            result.add(item);
-        }
-
-        // return list
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    public String toString()  {
-        return getClass().getName() + "{" + queue.size() + "}";
-    }
-}
diff --git a/weinre.server/src/weinre/server/ServerSettings.java b/weinre.server/src/weinre/server/ServerSettings.java
deleted file mode 100644
index 4a43094..0000000
--- a/weinre.server/src/weinre/server/ServerSettings.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.PosixParser;
-
-//-------------------------------------------------------------------
-public class ServerSettings {
-
-    final static private String BoundHostAllConstant = "-all-";
-
-    private int         httpPort           = 8080;
-    private String      boundHost          = "localhost";
-//  private boolean     useProxy           = false;
-    private boolean     reuseAddr          = true;
-    private boolean     verbose            = false;
-    private int         readTimeoutSeconds = 5;
-    private int         deathTimeoutSeconds;
-    private Properties  fileProperties;
-    private PrintWriter messageLog;
-
-    //---------------------------------------------------------------
-    static public ServerSettings getOptions(String[] commandLine) {
-        ServerSettings settings = new ServerSettings();
-        return settings.parse(commandLine);
-    }
-
-    //---------------------------------------------------------------
-    private ServerSettings() {
-        super();
-
-        fileProperties = fromPropertiesFile();
-    }
-
-    //---------------------------------------------------------------
-    private Options getOptions() {
-        Options options = new Options();
-
-        options.addOption("?",            false, "display help");
-        options.addOption("h", "help",    false, "display help");
-        options.addOption("httpPort",     true,  "tcp/ip port to use for the http server");
-        options.addOption("boundHost",    true,  "host address to bind to");
-        options.addOption("verbose",      true,  "display verbose logging information [true|false]");
-//      options.addOption("useProxy",     true,  "enable HTTP proxy [true|false]");
-        options.addOption("reuseAddr",    true,  "force bind the port if already bound [true|false]");
-        options.addOption("readTimeout",  true,  "seconds before timing out HTTP GETs");
-        options.addOption("deathTimeout", true,  "seconds before considering connector dead");
-        options.addOption("messageLog",   true,  "file to log messages to");
-
-        return options;
-    }
-
-    //---------------------------------------------------------------
-    public Map<String,Object> asProperties() {
-        Map<String,Object> result = new HashMap<String,Object>();
-
-        result.put("httpPort",     this.httpPort + "");
-        result.put("boundHost",    this.boundHost);
-        result.put("boundHosts",   this.getBoundHosts());
-        result.put("verbose",      this.verbose + "");
-//      result.setProperty("useProxy",     this.useProxy + "");
-        result.put("reuseAddr",    this.reuseAddr + "");
-        result.put("readTimeout",  this.readTimeoutSeconds + "");
-        result.put("deathTimeout", this.deathTimeoutSeconds + "");
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    private Properties fromPropertiesFile() {
-        Properties result = Utility.readPropertiesFile("server.properties");
-
-        // ya, Properties doesn't trim space off values
-        for (String key: result.stringPropertyNames()) {
-            String val = result.getProperty(key);
-            result.setProperty(key, val.trim());
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    private ServerSettings parse(String[] commandLineArgs) {
-        Options options = getOptions();
-
-        CommandLineParser parser = new PosixParser();
-        CommandLine       commandLine;
-        try {
-            commandLine = parser.parse(options, commandLineArgs);
-        }
-        catch (ParseException e) {
-            error(e.getMessage());
-            return null;
-        }
-
-        // handle help
-        if (commandLine.hasOption("?") || commandLine.hasOption("h")) {
-            printHelp(options);
-            return null;
-        }
-
-        // get values
-        httpPort            = getIntFromOption(commandLine,     "httpPort",     httpPort,             0, 0x00FFFF);
-        boundHost           = getStringFromOption(commandLine,  "boundHost",    boundHost);
-        verbose             = getBooleanFromOption(commandLine, "verbose",      verbose);
-//      useProxy            = getBooleanFromOption(commandLine, "useProxy",     useProxy);
-        reuseAddr           = getBooleanFromOption(commandLine, "reuseAddr",    reuseAddr);
-        readTimeoutSeconds  = getIntFromOption(commandLine,     "readTimeout",  readTimeoutSeconds,   0, 0x00FFFFFF);
-        deathTimeoutSeconds = getIntFromOption(commandLine,     "deathTimeout", readTimeoutSeconds*3, 0, 0x00FFFF);
-        messageLog          = getPrintWriterFromOption(commandLine, "messageLog");
-
-        // handle verbose logging
-        if (commandLine.hasOption("verbose")) {
-            verbose = true;
-        }
-
-        return this;
-    }
-
-    //---------------------------------------------------------------
-    private int getIntFromOption(CommandLine commandLine, String name, int defaultValue, int min, int max) {
-        int result = defaultValue;
-
-        String stringValue = commandLine.getOptionValue(name);
-        if (null == stringValue) {
-            stringValue = fileProperties.getProperty(name);
-        }
-
-        if (null == stringValue) return defaultValue;
-
-        try {
-            result = Integer.parseInt(stringValue);
-        }
-        catch (NumberFormatException e) {
-            error(name + " parameter must be numeric");
-            return result;
-        }
-
-        if ((result < min) || (result > 0x00FFFF)) {
-            error(name + " parameter must be between " + min + " and " + max);
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    private String getStringFromOption(CommandLine commandLine, String name, String defaultValue) {
-        String stringValue = commandLine.getOptionValue(name);
-        if (null == stringValue) {
-            stringValue = fileProperties.getProperty(name);
-        }
-
-        if (null == stringValue) return defaultValue;
-
-        return stringValue;
-    }
-
-    //---------------------------------------------------------------
-    private boolean getBooleanFromOption(CommandLine commandLine, String name, boolean defaultValue) {
-        boolean result = defaultValue;
-
-        String stringValue = commandLine.getOptionValue(name);
-        if (null == stringValue) {
-            stringValue = fileProperties.getProperty(name);
-        }
-
-        if (null == stringValue) return defaultValue;
-
-        result = Boolean.parseBoolean(stringValue);
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    private PrintWriter getPrintWriterFromOption(CommandLine commandLine, String name) {
-
-        String fileName = commandLine.getOptionValue(name);
-        if (null == fileName) {
-            fileName = fileProperties.getProperty(name);
-        }
-
-        if (null == fileName) return null;
-
-        File file = new File(fileName);
-
-        try {
-            FileWriter fileWriter = new FileWriter(file);
-            return new PrintWriter(fileWriter);
-        }
-        catch (IOException e) {
-            error(name + " parameter file name '" + fileName + "' cannot be opened for writing.");
-            return null;
-        }
-    }
-
-    //---------------------------------------------------------------
-    private void error(String message) {
-        System.out.println("error with command-line option: " + message);
-    }
-
-    //---------------------------------------------------------------
-    private void printHelp(Options options) {
-        new HelpFormatter().printHelp("java -jar weinre.jar [options]", options);
-    }
-
-    //---------------------------------------------------------------
-    public int getHttpPort() {
-        return httpPort;
-    }
-
-    //---------------------------------------------------------------
-    public String getBoundHost() {
-        return boundHost;
-    }
-
-    //---------------------------------------------------------------
-    public String[] getBoundHosts() {
-        if (getBoundHostValue() != null) {
-            return new String[] { getBoundHost() };
-        }
-
-        ArrayList<String> hosts = new ArrayList<String>();
-        List<NetworkInterface> networkInterfaces;
-        try {
-            networkInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
-        }
-        catch (SocketException e) {
-            return new String[]{"localhost"};
-        }
-
-        for (NetworkInterface networkInterface: networkInterfaces) {
-            List<InetAddress> inetAddresses = Collections.list(networkInterface.getInetAddresses());
-
-            for (InetAddress inetAddress: inetAddresses) {
-                hosts.add(inetAddress.getHostName());
-            }
-        }
-
-        return hosts.toArray(new String[]{});
-    }
-
-    //---------------------------------------------------------------
-    public String getBoundHostValue() {
-        if (BoundHostAllConstant.equals(boundHost)) return null;
-
-        return boundHost;
-    }
-
-    //---------------------------------------------------------------
-    public boolean getVerbose() {
-        return verbose;
-    }
-
-    //---------------------------------------------------------------
-    public int getReadTimeoutSeconds() {
-        return readTimeoutSeconds;
-    }
-
-    //---------------------------------------------------------------
-    public int getDeathTimeoutSeconds() {
-        return deathTimeoutSeconds;
-    }
-
-    //---------------------------------------------------------------
-    public boolean useProxy() {
-        return false; // useProxy;
-    }
-
-    //---------------------------------------------------------------
-    public boolean reuseAddr() {
-        return reuseAddr;
-    }
-
-    //---------------------------------------------------------------
-    public PrintWriter getMessageLog() {
-        return messageLog;
-    }
-
-    //---------------------------------------------------------------
-    public String getNiceHostName() {
-        String hostName = getBoundHostValue();
-        if (null == hostName) return "localhost";
-        return hostName;
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings("unused")
-    private String getSuperNiceHostName() {
-        String hostName = getBoundHost();
-
-        // get the host address used
-        InetAddress inetAddress;
-        try {
-            inetAddress = InetAddress.getByName(hostName);
-        }
-        catch (UnknownHostException e) {
-            Main.warn("Unable to get host address of " + hostName);
-            return null;
-        }
-
-        // if it's "any local address", deal with that
-        if (inetAddress.isAnyLocalAddress()) {
-            try {
-                InetAddress oneAddress = InetAddress.getLocalHost();
-                return oneAddress.getHostName();
-            }
-            catch (UnknownHostException e) {
-                Main.warn("Unable to get any local host address");
-                return null;
-            }
-        }
-
-        return inetAddress.getHostName();
-    }
-}
diff --git a/weinre.server/src/weinre/server/Target.java b/weinre.server/src/weinre/server/Target.java
deleted file mode 100644
index 8bb3113..0000000
--- a/weinre.server/src/weinre/server/Target.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.wink.json4j.JSONArray;
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-//-------------------------------------------------------------------
-public class Target extends Connector {
-
-    private List<Client> connectedClients;
-    private String       url;
-
-    //---------------------------------------------------------------
-    public Target(Channel channel, String url) {
-        super(channel);
-
-        connectedClients = new ArrayList<Client>();
-        this.url = url;
-        _register();
-
-    }
-
-    //---------------------------------------------------------------
-    public String getURL() {
-        return this.url;
-    }
-
-    //---------------------------------------------------------------
-    public boolean isTarget() {
-        return true;
-    }
-
-    //---------------------------------------------------------------
-    public List<Client> getConnectedClients() {
-        List<Client> result = new LinkedList<Client>();
-
-        Lock.lock();
-        try {
-            result.addAll(connectedClients);
-        }
-        finally {
-            Lock.unlock();
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    protected void _connect(Client client) {
-        if (null == client) return;
-
-        Lock.lock();
-
-        try {
-            if (connectedClients.contains(client)) return;
-
-            connectedClients.add(client);
-        }
-        finally {
-            Lock.unlock();
-        }
-    }
-
-    //---------------------------------------------------------------
-    protected void _disconnect(Client client) {
-        if (null == client) return;
-
-        Lock.lock();
-
-        try {
-            if (!connectedClients.contains(client)) return;
-
-            connectedClients.remove(client);
-        }
-        finally {
-            Lock.unlock();
-        }
-    }
-
-    //---------------------------------------------------------------
-    public JSONObject getDescription() {
-        JSONObject result = new JSONObject();
-
-        try {
-            result.put("channel",            getChannel().getName());
-            result.put("id",                 getChannel().getId());
-            result.put("hostName",           getChannel().getRemoteHost());
-            result.put("url",                this.url);
-            result.put("connectedClientIds", new JSONArray());
-        } catch (JSONException e) {
-            throw new RuntimeException(e);
-        }
-
-        return result;
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/Utility.java b/weinre.server/src/weinre/server/Utility.java
deleted file mode 100644
index cc1dca4..0000000
--- a/weinre.server/src/weinre/server/Utility.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.security.SecureRandom;
-import java.util.Properties;
-
-//-------------------------------------------------------------------
-public class Utility {
-
-    static private int SequenceNumber = 1 + new SecureRandom().nextInt(Integer.MAX_VALUE - 1);
-
-    //---------------------------------------------------------------
-    private Utility() {}
-
-    //---------------------------------------------------------------
-    static public synchronized int getNextSequenceNumber() {
-        int result = SequenceNumber;
-
-        SequenceNumber = (result == Integer.MAX_VALUE) ? 1 : result + 1;
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    static public String reverse(String string) {
-        char[] responseChars = string.toCharArray();
-
-        for (int i=0; i<responseChars.length/2; i++) {
-            char tmp                                = responseChars[responseChars.length-i-1];
-            responseChars[responseChars.length-i-1] = responseChars[i];
-            responseChars[i]                        = tmp;
-        }
-        return String.valueOf(responseChars);
-    }
-
-    //---------------------------------------------------------------
-    static public byte[] reverse(byte[] data, int offset, int length) {
-        byte[] response = new byte[length];
-
-        for (int i=0; i<length; i++) {
-            response[i] = data[offset + length - i - 1];
-        }
-
-        return response;
-    }
-
-    //---------------------------------------------------------------
-    static public Properties readPropertiesFile(String fileName) {
-        Properties result = new Properties();
-
-        String userHome = System.getProperty("user.home");
-        if (null == userHome) {
-            Main.warn("System property user.home not set!");
-            return result;
-        }
-
-        File file = new File(new File(userHome, ".weinre"), fileName);
-
-        if (!file.exists()) return result;
-
-        FileReader fr = null;
-        try {
-            fr = new FileReader(file);
-            result.load(fr);
-        }
-        catch (IOException e) {
-            Main.warn("Exception reading '" + file.getAbsolutePath() + "': " + e);
-        }
-        finally {
-            try { if (fr != null) fr.close(); } catch (Exception e) {}
-        }
-
-        // ya, Properties doesn't trim space off values
-        for (String key: result.stringPropertyNames()) {
-            String val = result.getProperty(key);
-            result.setProperty(key, val.trim());
-        }
-
-        return result;
-    }
-
-    //---------------------------------------------------------------
-    static public void writePropertiesFile(String fileName, Properties properties) {
-        String userHome = System.getProperty("user.home");
-        if (null == userHome) {
-            Main.warn("System property user.home not set!");
-            return;
-        }
-
-        File file = new File(userHome, ".weinre");
-        if (!file.exists()) {
-            if (!file.mkdir()) {
-                Main.warn("unable to create directory ~/.weinre");
-                return;
-            }
-        }
-
-        if (!file.isDirectory()) {
-            Main.warn("can't write ~/.weinre/" + fileName + " since ~/.weinre is not a directory");
-            return;
-        }
-
-        file = new File(file, fileName);
-        FileWriter fw = null;
-        try {
-            fw = new FileWriter(file);
-            properties.store(fw, fileName);
-        }
-        catch (IOException e) {
-            Main.warn("Exception writing '" + file.getAbsolutePath() + "': " + e);
-        }
-        finally {
-            try { if (fw != null) fw.close(); } catch (Exception e) {}
-        }
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/WatchDog.java b/weinre.server/src/weinre/server/WatchDog.java
deleted file mode 100644
index 327e287..0000000
--- a/weinre.server/src/weinre/server/WatchDog.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server;
-
-import java.util.List;
-
-//-------------------------------------------------------------------
-public class WatchDog {
-
-    public static long ChannelLivelinessTimeout = 5000;
-
-    //---------------------------------------------------------------
-    static public void start() {
-
-        final WatchDog watchDog = new WatchDog();
-
-        Runnable runnable = new Runnable() {
-            public void run() { watchDog.run(); }
-        };
-
-        Thread thread = new Thread(runnable, watchDog.getClass().getName());
-
-        thread.start();
-    }
-
-    //---------------------------------------------------------------
-    private WatchDog() {
-        super();
-    }
-
-    //---------------------------------------------------------------
-    private void run() {
-        while(true) {
-            sleep();
-
-            checkForDeadChannels();
-        }
-    }
-
-    //---------------------------------------------------------------
-    private void checkForDeadChannels() {
-        List<Channel> channels = ChannelManager.$.getChannels();
-
-        int deathTimeout = Main.getSettings().getDeathTimeoutSeconds() * 1000;
-
-        long currentTime = System.currentTimeMillis();
-        for (Channel channel: channels) {
-            long lastRead = channel.getLastRead();
-
-            if (currentTime - lastRead > deathTimeout) {
-                channel.close();
-            }
-        }
-    }
-
-    //---------------------------------------------------------------
-    private void sleep() {
-        try {
-            Thread.sleep(1000);
-        }
-        catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
diff --git a/weinre.server/src/weinre/server/http/ClassPathResourceHandler.java b/weinre.server/src/weinre/server/http/ClassPathResourceHandler.java
deleted file mode 100644
index fc0e88f..0000000
--- a/weinre.server/src/weinre/server/http/ClassPathResourceHandler.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.util.resource.Resource;
-
-import weinre.server.ExtensionManager;
-
-//-------------------------------------------------------------------
-public class ClassPathResourceHandler extends ResourceHandler {
-
-    private String pathPrefix;
-
-    //---------------------------------------------------------------
-    public ClassPathResourceHandler(String pathPrefix) {
-        super();
-
-        this.pathPrefix = pathPrefix;
-    }
-
-    //---------------------------------------------------------------
-    public Resource getResource(String path) throws MalformedURLException {
-        if ((path == null) || !path.startsWith("/")) {
-            throw new MalformedURLException(path);
-        }
-
-        // handle extensions
-        if (path.startsWith("/client/extensions/")) {
-            return ExtensionManager.getResource(path);
-        }
-
-        path = pathPrefix + path;
-        URL url = getClass().getClassLoader().getResource(path);
-        if (url != null)
-            try {
-                return Resource.newResource(url);
-            }
-            catch (IOException e) {
-                throw new MalformedURLException();
-            }
-
-        return null;
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/http/DebugHandler.java b/weinre.server/src/weinre/server/http/DebugHandler.java
deleted file mode 100644
index 8121f03..0000000
--- a/weinre.server/src/weinre/server/http/DebugHandler.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Enumeration;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
-
-
-/**
-* Debug Handler.
-* A lightweight debug handler that can be used in production code.
-* Details of the request and response are written to an output stream
-* and the current thread name is updated with information that will link
-* to the details in that output.
-*/
-public class DebugHandler extends HandlerWrapper {
-
-    //---------------------------------------------------------------
-    public void handle(String target, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException {
-        try {
-            getHandler().handle(target, request, servletRequest, servletResponse);
-        }
-        catch(IOException e) {
-          throw new RuntimeException(e);
-        }
-
-        Response response = request.getResponse();
-
-        dump(System.out, target, request, response);
-    }
-
-    //---------------------------------------------------------------
-    private void dump(PrintStream oStream, String target, Request request, Response response) {
-        oStream.println("----------------------------------------------------------");
-        oStream.println("target: " + target);
-
-        oStream.println("request:");
-        oStream.println("   headers:");
-        dumpHeaders(oStream, request);
-
-        oStream.println("response:");
-        oStream.println("   status: " + response.getStatus());
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings("rawtypes")
-    private void dumpHeaders(PrintStream oStream, Request request) {
-        Enumeration e = request.getHeaderNames();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            Enumeration e2 = request.getHeaders(name);
-            while (e2.hasMoreElements()) {
-                String value = (String) e2.nextElement();
-                oStream.println("      " + name + ": " + value);
-            }
-        }
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/http/FilteredRequestLogHandler.java b/weinre.server/src/weinre/server/http/FilteredRequestLogHandler.java
deleted file mode 100644
index 1a88e88..0000000
--- a/weinre.server/src/weinre/server/http/FilteredRequestLogHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.RequestLogHandler;
-
-//-------------------------------------------------------------------
-public class FilteredRequestLogHandler extends RequestLogHandler {
-
-    //---------------------------------------------------------------
-    @Override
-    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        int status = baseRequest.getResponse().getStatus();
-
-        if (status == 200) return;
-        if (status == 304) return;
-
-        super.handle(target, baseRequest, request, response);
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/http/HttpServer.java b/weinre.server/src/weinre/server/http/HttpServer.java
deleted file mode 100644
index e9a5f7c..0000000
--- a/weinre.server/src/weinre/server/http/HttpServer.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.NCSARequestLog;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.server.handler.HandlerList;
-import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.util.component.LifeCycle;
-
-import weinre.server.Main;
-import weinre.server.ServerSettings;
-
-//-------------------------------------------------------------------
-public class HttpServer {
-
-    private Main           main;
-    private ServerSettings settings;
-
-    //---------------------------------------------------------------
-    public HttpServer(Main main, ServerSettings settings) {
-        super();
-
-        this.main     = main;
-        this.settings = settings;
-    }
-
-    //---------------------------------------------------------------
-    public Server run() throws Exception {
-        String hostName     = settings.getBoundHostValue();
-        String niceHostName = settings.getNiceHostName();
-
-        SelectChannelConnector connector = new SelectChannelConnector();
-
-        connector.setHost(hostName);
-        connector.setPort(settings.getHttpPort());
-        connector.setReuseAddress(settings.reuseAddr());
-        connector.setResolveNames(true);
-
-        Server server = new Server();
-        server.setConnectors(new Connector[] { connector });
-        server.addLifeCycleListener(new LifeCycle.Listener() {
-            public void lifeCycleStarting(LifeCycle event) {}
-            public void lifeCycleStarted(LifeCycle event) { main.serverStarted(); }
-            public void lifeCycleFailure(LifeCycle event, Throwable cause) {}
-            public void lifeCycleStopping(LifeCycle event) {}
-            public void lifeCycleStopped(LifeCycle event) {}
-        });
-
-        // set up the main handlers
-        HandlerList handlers = new HandlerList();
-
-        // debug handler
-//        DebugHandler debugHandler = new DebugHandler();
-//        handlers.addHandler(debugHandler);
-
-        HttpSocketHandler httpSocketHandler;
-
-        // client socket handler
-        httpSocketHandler = new HttpSocketHandler("/ws/client");
-        handlers.addHandler(httpSocketHandler);
-
-        // target socket handler
-        httpSocketHandler = new HttpSocketHandler("/ws/target");
-        handlers.addHandler(httpSocketHandler);
-
-//        runChannelTester();
-
-        // handler for /web (static files in jar)
-        ClassPathResourceHandler handlerStaticFiles = new ClassPathResourceHandler("web");
-        handlers.addHandler(handlerStaticFiles);
-
-        // outer collection of handlers for management
-        HandlerCollection handlerOuter = new HandlerCollection();
-
-        // add the main handlers
-        handlerOuter.addHandler(handlers);
-
-        // add a request logger
-        RequestLogHandler requestLogHandler = new FilteredRequestLogHandler();
-
-        NCSARequestLog requestLog = new NCSARequestLog();
-        requestLog.setRetainDays(90);
-        requestLog.setAppend(true);
-        requestLog.setExtended(false);
-        requestLog.setLogTimeZone("GMT");
-        requestLogHandler.setRequestLog(requestLog);
-
-        handlerOuter.addHandler(requestLogHandler);
-
-        // serve with the outer handler
-        server.setHandler(handlerOuter);
-
-        // start the JS thread
-//        JavaScriptRunner.runThreaded("server/main.js", null, null);
-
-        // start the server
-        try {
-            server.start();
-        }
-        catch (IOException e) {
-            throw e;
-        }
-
-        Main.info("HTTP server started at http://" + niceHostName + ":" + settings.getHttpPort());
-
-        return server;
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/http/HttpSocketHandler.java b/weinre.server/src/weinre/server/http/HttpSocketHandler.java
deleted file mode 100644
index 1da4f2a..0000000
--- a/weinre.server/src/weinre/server/http/HttpSocketHandler.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.wink.json4j.JSONArray;
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-
-import weinre.server.Channel;
-import weinre.server.ChannelManager;
-import weinre.server.Main;
-import weinre.server.Utility;
-
-//-------------------------------------------------------------------
-public class HttpSocketHandler extends AbstractHandler {
-    private String pathPrefix;
-    private int    pathPrefixParts;
-
-    //---------------------------------------------------------------
-    public HttpSocketHandler(String pathPrefix) {
-        super();
-
-        this.pathPrefix      = pathPrefix;
-        this.pathPrefixParts = pathPrefix.split("/").length;
-    }
-
-    //---------------------------------------------------------------
-    @Override
-    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        // ! * pathPrefix*
-        if (!target.startsWith(pathPrefix)) return;
-
-        String method = baseRequest.getMethod();
-
-        setCORSHeaders(response);
-        setCacheHeaders(response);
-
-        // OPTIONS pathPrefix
-        if (target.equals(pathPrefix) && method.equals("OPTIONS")) {
-            baseRequest.setHandled(true);
-            handleOptions(target, baseRequest, request, response);
-            return;
-        }
-
-        // POST pathPrefix
-        if (target.equals(pathPrefix) && method.equals("POST")) {
-            baseRequest.setHandled(true);
-            handleCreate(target, baseRequest, request, response);
-            return;
-        }
-
-        // * pathPrefix
-        if (target.equals(pathPrefix)) {
-            baseRequest.setHandled(true);
-            response.sendError(405);
-            return;
-        }
-
-        // * pathPrefix/x/*
-        String[] parts = target.split("/");
-        if (parts.length != pathPrefixParts + 1) {
-            baseRequest.setHandled(true);
-            response.sendError(404);
-        }
-
-        //
-        if (parts.length <= pathPrefixParts) {
-            baseRequest.setHandled(true);
-            response.sendError(405);
-        }
-
-        String channel = parts[pathPrefixParts];
-
-        // OPTIONS pathPrefix/x
-        if (method.equals("OPTIONS")) {
-            baseRequest.setHandled(true);
-            handleOptions(target, baseRequest, request, response);
-            return;
-        }
-
-        // GET pathPrefix/x
-        if (method.equals("GET")) {
-            baseRequest.setHandled(true);
-            handleGet(channel, target, baseRequest, request, response);
-            return;
-        }
-
-        // POST pathPrefix/x
-        if (method.equals("POST")) {
-            baseRequest.setHandled(true);
-            handlePost(channel, target, baseRequest, request, response);
-            return;
-        }
-
-        // * pathPrefix/x
-        baseRequest.setHandled(true);
-        response.sendError(405);
-    }
-
-    //---------------------------------------------------------------
-    private void setCORSHeaders(HttpServletResponse response) {
-        response.setHeader("Access-Control-Allow-Origin", "*");
-        response.setHeader("Access-Control-Max-Age", "600");
-        response.setHeader("Access-Control-Allow-Methods", "GET, POST");
-    }
-
-    //---------------------------------------------------------------
-    private void setCacheHeaders(HttpServletResponse response) {
-        response.setHeader("Pragma",        "no-cache");
-        response.setHeader("Expires",       "0");
-        response.setHeader("Cache-Control", "no-cache");
-        response.setHeader("Cache-Control", "no-store");
-    }
-
-    //---------------------------------------------------------------
-    public void handleOptions(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        response.setStatus(200);
-        response.setContentType("text/plain");
-    }
-
-    //---------------------------------------------------------------
-    public void handleCreate(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        String channelName = "" + Utility.getNextSequenceNumber();
-        String id;
-
-        if (0 == baseRequest.getContentLength()) {
-            id = Channel.AnonymousId;
-        }
-
-        else {
-            try {
-                String json = readRequestBody(request.getInputStream());
-                JSONObject obj = new JSONObject(json);
-                if (!obj.has("id")) {
-                    id = Channel.AnonymousId;
-                }
-                else {
-                    id = obj.getString("id");
-                    if (id.isEmpty()) {
-                        id = Channel.AnonymousId;
-                    }
-                }
-            }
-            catch (IOException e) {
-                response.setStatus(400);
-                return;
-            }
-            catch (JSONException e) {
-                response.setStatus(400);
-                return;
-            }
-        }
-
-        ChannelManager.$.registerChannel(pathPrefix, channelName, id, request.getRemoteHost(), request.getRemoteAddr());
-
-        response.setStatus(200);
-        response.setContentType("application/json");
-
-        ServletOutputStream oStream = response.getOutputStream();
-        JSONObject obj = new JSONObject();
-
-        try {
-            obj.put("channel", channelName);
-            obj.put("id", id);
-        }
-        catch (JSONException e) {
-            throw new RuntimeException(e);
-        }
-
-        String result = obj.toString();
-        oStream.print(result);
-        oStream.close();
-    }
-
-    //---------------------------------------------------------------
-    public void handleGet(String channelName, String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        Channel channel = ChannelManager.$.getChannel(channelName, request.getRemoteAddr());
-        if (null == channel) {
-            response.setStatus(404);
-            return;
-        }
-
-        channel.updateLastRead();
-
-        List<String> json;
-        try {
-            json = channel.getResponses(Main.getSettings().getReadTimeoutSeconds());
-        }
-        catch (InterruptedException e) {
-            throw new IOException(e);
-        }
-
-        response.setStatus(200);
-        response.setContentType("application/json");
-
-        ServletOutputStream oStream = response.getOutputStream();
-        printJSONList(oStream, json);
-
-        oStream.close();
-    }
-
-    //---------------------------------------------------------------
-    private void printJSONList(ServletOutputStream oStream, List<String> json) throws IOException {
-        try {
-            oStream.print(new JSONArray(json).toString());
-        }
-        catch (JSONException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    //---------------------------------------------------------------
-    public void handlePost(String channelName, String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-        Channel channel = ChannelManager.$.getChannel(channelName, request.getRemoteAddr());
-        if (null == channel) {
-            response.setStatus(404);
-            return;
-        }
-
-//        if (!"text/plain".equals(baseRequest.getContentType())) {
-//            response.setStatus(415);
-//            return;
-//        }
-
-        if (0 == baseRequest.getContentLength()) {
-            response.setStatus(400);
-            return;
-        }
-
-        try {
-            String json = readRequestBody(request.getInputStream());
-            channel.postRequest(json);
-        }
-        catch (IOException e) {
-            response.setStatus(400);
-            return;
-        }
-
-        response.setStatus(200);
-        response.setContentType("text/plain");
-        response.getOutputStream().close();
-    }
-
-    //---------------------------------------------------------------
-    private String readRequestBody(InputStream is) throws IOException {
-        StringBuffer stringBuffer = new StringBuffer();
-        Reader       reader       = new InputStreamReader(is, "UTF-8");
-        char[]       buffer       = new char[4096];
-
-        int read;
-        while ((read = reader.read(buffer)) > 0) {
-            stringBuffer.append(buffer, 0, read);
-        }
-
-        return stringBuffer.toString();
-    }
-}
diff --git a/weinre.server/src/weinre/server/http/ProxyServer.java b/weinre.server/src/weinre/server/http/ProxyServer.java
deleted file mode 100644
index 1150424..0000000
--- a/weinre.server/src/weinre/server/http/ProxyServer.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.http;
-
-import java.io.IOException;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.NCSARequestLog;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.HandlerList;
-import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlets.ProxyServlet;
-
-import weinre.server.Main;
-import weinre.server.ServerSettings;
-
-//-------------------------------------------------------------------
-public class ProxyServer {
-    private ServerSettings settings;
-
-    //---------------------------------------------------------------
-    public ProxyServer(ServerSettings settings) {
-        super();
-
-        this.settings = settings;
-    }
-
-    //---------------------------------------------------------------
-    public void run() throws Exception {
-        SelectChannelConnector connector = new SelectChannelConnector();
-
-        connector = new SelectChannelConnector();
-
-        String hostName = settings.getBoundHost();
-
-        connector.setHost(hostName);
-        connector.setPort(settings.getHttpPort()+1);
-        connector.setReuseAddress(false);
-
-        Server proxyServer = new Server();
-        proxyServer.setConnectors(new Connector[] { connector });
-
-        HandlerList handlers = new HandlerList();
-
-        handlers = new HandlerList();
-
-        RequestLogHandler requestLogHandler = new RequestLogHandler();
-
-        requestLogHandler = new RequestLogHandler();
-
-        NCSARequestLog requestLog;
-
-        requestLog = new NCSARequestLog();
-        requestLog.setRetainDays(90);
-        requestLog.setAppend(true);
-        requestLog.setExtended(false);
-        requestLog.setLogTimeZone("GMT");
-        requestLogHandler.setRequestLog(requestLog);
-
-        handlers.addHandler(requestLogHandler);
-
-        ServletContextHandler handlerProxy = new ServletContextHandler();
-        handlerProxy.setContextPath("/");
-        ProxyServlet proxyServlet = new ProxyServlet();
-        handlerProxy.addServlet(new ServletHolder(proxyServlet), "/");
-        handlers.addHandler(handlerProxy);
-
-        proxyServer.setHandler(handlers);
-
-        try {
-            proxyServer.start();
-        }
-        catch (IOException e) {
-            Main.warn("unable to start proxy server: " + e.getMessage());
-            proxyServer.stop();
-        }
-
-        Main.info("HTTP proxy server started at http://" + settings.getNiceHostName() + ":" + (settings.getHttpPort()+1));
-    }
-}
diff --git a/weinre.server/src/weinre/server/service/WeinreClientCommands.java b/weinre.server/src/weinre/server/service/WeinreClientCommands.java
deleted file mode 100644
index 3d5e16d..0000000
--- a/weinre.server/src/weinre/server/service/WeinreClientCommands.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.service;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.wink.json4j.JSONArray;
-import org.apache.wink.json4j.JSONException;
-import org.apache.wink.json4j.JSONObject;
-
-import weinre.server.Channel;
-import weinre.server.Client;
-import weinre.server.ConnectionManager;
-import weinre.server.ExtensionManager;
-import weinre.server.Main;
-import weinre.server.Target;
-
-//-------------------------------------------------------------------
-public class WeinreClientCommands {
-
-    //---------------------------------------------------------------
-    public void registerClient(Channel channel, String callbackId) throws IOException {
-        Client client = new Client(channel);
-
-        JSONObject description = client.getDescription();
-
-        channel.sendCallback("WeinreClientEvents", callbackId, description);
-        channel.sendEvent("WeinreClientEvents", "serverProperties", Main.getSettings().asProperties());
-    }
-
-    //---------------------------------------------------------------
-    public void getTargets(Channel channel, String callbackId) throws IOException {
-        List<Target> targets = ConnectionManager.$.getTargets(channel.getId());
-        JSONArray targetResults = new JSONArray();
-
-        for (Target target: targets) {
-            targetResults.add(target.getDescription());
-        }
-
-        channel.sendCallback("WeinreClientEvents", callbackId, targetResults);
-    }
-
-    //---------------------------------------------------------------
-    public void getClients(Channel channel, String callbackId) throws IOException {
-        List<Client> clients = ConnectionManager.$.getClients(channel.getId());
-        JSONArray clientResults = new JSONArray();
-
-        for (Client client: clients) {
-            clientResults.add(client.getDescription());
-        }
-
-        channel.sendCallback("WeinreClientEvents", callbackId, clientResults);
-    }
-
-    //---------------------------------------------------------------
-    public void getExtensions(Channel channel, String callbackId) throws IOException {
-        String[]  extensions = ExtensionManager.getExtensions();
-        JSONArray result     = new JSONArray();
-
-        try {
-            for (String extension: extensions) {
-                JSONObject extensionObject = new JSONObject();
-                extensionObject.put("startPage", "extensions/" + extension + "/extension.html");
-
-                result.add(extensionObject);
-            }
-        }
-        catch(JSONException e) {
-            throw new RuntimeException(e);
-        }
-
-        channel.sendCallback("WeinreClientEvents", callbackId, result);
-    }
-
-    //---------------------------------------------------------------
-    public void connectTarget(Channel channel, String clientId, String targetId, String callbackId) {
-        Client client = ConnectionManager.$.getClient(clientId);
-        if (client == null) return;
-
-        Target target = ConnectionManager.$.getTarget(targetId);
-        if (target == null) return;
-
-        ConnectionManager.$.connect(client, target);
-    }
-
-    //---------------------------------------------------------------
-    public void disconnectTarget(Channel channel, String clientId, String callbackId) {
-        Client client = ConnectionManager.$.getClient(clientId);
-        if (client == null) return;
-
-        Target target = client.getConnectedTarget();
-        if (target == null) return;
-
-        ConnectionManager.$.disconnect(client, target);
-    }
-
-    //---------------------------------------------------------------
-    public void logDebug(Channel channel, String message, String callbackId) {
-        Main.debug("client " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logInfo(Channel channel, String message, String callbackId) {
-        Main.info("client " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logWarning(Channel channel, String message, String callbackId) {
-        Main.warn("client " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logError(Channel channel, String message, String callbackId) {
-        Main.error("client " + channel.getName() + ": " + message);
-    }
-
-}
diff --git a/weinre.server/src/weinre/server/service/WeinreTargetCommands.java b/weinre.server/src/weinre/server/service/WeinreTargetCommands.java
deleted file mode 100644
index 139d45c..0000000
--- a/weinre.server/src/weinre/server/service/WeinreTargetCommands.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package weinre.server.service;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.wink.json4j.JSONObject;
-
-import weinre.server.Channel;
-import weinre.server.ChannelManager;
-import weinre.server.Main;
-import weinre.server.Target;
-
-//-------------------------------------------------------------------
-public class WeinreTargetCommands {
-
-    //---------------------------------------------------------------
-    public void registerTarget(Channel channel, String url, String callbackId) throws IOException {
-        Target target = new Target(channel, url);
-
-        JSONObject description = target.getDescription();
-
-        channel.sendCallback("WeinreTargetEvents", callbackId, description);
-    }
-
-    //---------------------------------------------------------------
-    @SuppressWarnings("unchecked")
-    public void sendClientCallback(Channel channel, String clientCallbackId, Object args, String callbackId) throws IOException {
-        Object[] argsArray;
-        if (null == args)
-            argsArray = new Object[0];
-        else
-            argsArray = ((List<Object>) args).toArray();
-
-        // the channel to send the callback to is embedded in the callbackId
-        String callbackConnectorId = getCallbackConnectorId(clientCallbackId);
-        if (null == callbackConnectorId) {
-            Main.warn(getClass().getName() + ".sendClientCallback() sent with invalid callbackId: " + clientCallbackId);
-            return;
-        }
-
-        channel = ChannelManager.$.getChannel(callbackConnectorId);
-        if (null == channel) {
-            // indication that channel was closed; this message may generate a lot of noise
-            Main.warn(getClass().getName() + ".sendClientCallback() unable to find channel : " + callbackConnectorId);
-            return;
-        }
-
-        channel.sendCallback("WeinreClientEvents", clientCallbackId, argsArray);
-    }
-
-    //---------------------------------------------------------------
-    public void logDebug(Channel channel, String message, String callbackId) {
-        Main.debug("target " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logInfo(Channel channel, String message, String callbackId) {
-        Main.info("target " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logWarning(Channel channel, String message, String callbackId) {
-        Main.warn("target " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    public void logError(Channel channel, String message, String callbackId) {
-        Main.error("target " + channel.getName() + ": " + message);
-    }
-
-    //---------------------------------------------------------------
-    private String getCallbackConnectorId(String callbackId) {
-        int index = callbackId.indexOf("::");
-        return callbackId.substring(0, index);
-    }
-
-}
diff --git a/weinre.server/weinre b/weinre.server/weinre
new file mode 100755
index 0000000..d1b9904
--- /dev/null
+++ b/weinre.server/weinre
@@ -0,0 +1,33 @@
+#!/usr/bin/env node
+
+/*
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+*/
+
+// script to run the weinre server
+
+var path = require('path')
+var fs   = require('fs')
+var lib  = path.join(path.dirname(fs.realpathSync(__filename)), 'lib')
+
+require('coffee-script')
+
+var cli = require(lib + '/cli')
+cli.run()
diff --git a/weinre.server/weinre server using ~weinre-server.settings.launch b/weinre.server/weinre server using ~weinre-server.settings.launch
deleted file mode 100644
index 88ae404..0000000
--- a/weinre.server/weinre server using ~weinre-server.settings.launch
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/weinre.server/src/weinre/server/Main.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="weinre.server.Main"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--verbose   true --deathTimeout 120"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="weinre.server"/>
-</launchConfiguration>
diff --git a/weinre.server/weinre-hot b/weinre.server/weinre-hot
new file mode 100755
index 0000000..2287149
--- /dev/null
+++ b/weinre.server/weinre-hot
@@ -0,0 +1,30 @@
+#/bin/sh
+
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+# Script to run the weinre server under node-supervisor.
+#
+# Only checks the build output weinre.build/out/build-done.txt
+# to determine whether to kill and restart the server.
+
+cd `dirname $0`
+supervisor -n -p 1 -e txt -w ../weinre.build/out/build-done.txt ./weinre
+
+# supervisor: https://github.com/isaacs/node-supervisor
\ No newline at end of file
diff --git a/weinre.web/.classpath b/weinre.web/.classpath
deleted file mode 100644
index 8778ddd..0000000
--- a/weinre.web/.classpath
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/weinre.web/.project b/weinre.web/.project
deleted file mode 100644
index dba441d..0000000
--- a/weinre.web/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>weinre.web</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/weinre.web/demo/split.html b/weinre.web/demo/split.html
new file mode 100644
index 0000000..1e2222a
--- /dev/null
+++ b/weinre.web/demo/split.html
@@ -0,0 +1,23 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+-->
+
+<frameset rows="50%,50%">  
+  <frame src="/demo/weinre-demo.html" />  
+  <frame src="/client" />  
+</frameset>
\ No newline at end of file
diff --git a/weinre.web/index.html b/weinre.web/index.html
index 3afbc14..fd835b6 100644
--- a/weinre.web/index.html
+++ b/weinre.web/index.html
@@ -100,15 +100,8 @@
 <h2>Versions</h2>
 
 <table>
-<tr><td>weinre:         <td> <span id="version-weinre">???</span> <span id="version-build">???</span>
-<tr><td>webkit:         <td> <span id="version-webkit">???</span>
-<tr><td>swt:            <td> <span id="version-swt">???</span>
-<tr><td>jetty:          <td> <span id="version-jetty">???</span>
-<tr><td>jetty servlet:  <td> <span id="version-servlet">???</span>
-<tr><td>apache cli:     <td> <span id="version-cli">???</span>
-<tr><td>apache json4j:  <td> <span id="version-json4j">???</span>
-<tr><td>json2:          <td> <span id="version-json2">???</span>
-<tr><td>modjewel:       <td> <span id="version-modjewel">???</span>
+<tr><td>weinre: <td> <span id="version-weinre">???</span> 
+<tr><td>build:  <td> <span id="version-build">???</span>
 </table>
 
 <img src="images/weinre-icon-128x128.png">
diff --git a/weinre.web/index.js b/weinre.web/index.js
index 86e8508..9153fbe 100644
--- a/weinre.web/index.js
+++ b/weinre.web/index.js
@@ -35,19 +35,9 @@
 replaceURL("url-target-script",          buildHttpURL("target/target-script-min.js#" + weinre_id))
 replaceURL("url-target-bookmarklet",     getTargetBookmarklet(), "weinre target debug")
 replaceURL("url-target-documentation",   buildHttpURL("doc/"))
-//replaceURL("url-client-protocol",        buildHttpURL("ws/client/"))
-//replaceURL("url-target-protocol",        buildHttpURL("ws/target/"))
 
 replaceText("version-weinre",    Weinre.Versions.weinre)
 replaceText("version-build",     Weinre.Versions.build)
-replaceText("version-webkit",    Weinre.Versions.webkit)
-replaceText("version-jetty",     Weinre.Versions.jetty)
-replaceText("version-servlet",   Weinre.Versions.servlet)
-replaceText("version-cli",       Weinre.Versions.cli)
-replaceText("version-json4j",    Weinre.Versions.json4j)
-replaceText("version-json2",     Weinre.Versions.json2)
-replaceText("version-swt",       Weinre.Versions.swt)
-replaceText("version-modjewel",  Weinre.Versions.modjewel)
 
 replaceText("target-bookmarklet-src-pre",       getTargetBookmarklet())
 replaceText("target-bookmarklet-src-text-area", getTargetBookmarklet())
diff --git a/weinre.web/interfaces/interfaces.html b/weinre.web/interfaces/interfaces.html
index 9797ebf..78f9f57 100644
--- a/weinre.web/interfaces/interfaces.html
+++ b/weinre.web/interfaces/interfaces.html
@@ -24,7 +24,7 @@
     <head>
         <title>weinre interfaces</title>
         <link rel="stylesheet" href="interfaces.css">
-        <script src="/modjewel-require.js"></script>
+        <script src="/modjewel.js"></script>
         <script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>
         <script src="/weinre/common/Weinre.transportd.js"></script>
         <script src="/weinre/common/Ex.transportd.js"></script>
diff --git a/weinre.web/modjewel.js b/weinre.web/modjewel.js
new file mode 100644
index 0000000..5f84d9c
--- /dev/null
+++ b/weinre.web/modjewel.js
@@ -0,0 +1,374 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+//----------------------------------------------------------------------------
+// an implementation of the require() function as specified for use with
+// CommonJS Modules - see http://commonjs.org/specs/modules/1.0.html
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// inspired from David Flanagan's require() function documented here:
+// http://www.davidflanagan.com/2009/11/a-module-loader.html
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// only supports "preloaded" modules ala define() (AMD)
+//    http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition
+// but the id parameter is required
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// function wrapper
+//----------------------------------------------------------------------------
+(function(){
+
+//----------------------------------------------------------------------------
+// some constants
+//----------------------------------------------------------------------------
+var PROGRAM = "modjewel"
+var VERSION = "1.2.0"
+var global  = this
+
+//----------------------------------------------------------------------------
+// if require() is already defined, leave
+//----------------------------------------------------------------------------
+if (global.modjewel) {
+    log("modjewel global variable already defined")
+    return
+}
+
+global.modjewel = null
+
+var OriginalRequire = global.require
+var OriginalDefine  = global.define
+var NoConflict      = false
+
+//----------------------------------------------------------------------------
+// "globals" (local to this function scope though)
+//----------------------------------------------------------------------------
+var ModuleStore
+var ModulePreloadStore
+var MainModule
+var WarnOnRecursiveRequire = false
+
+//----------------------------------------------------------------------------
+// the require function
+//----------------------------------------------------------------------------
+function get_require(currentModule) {
+    var result = function require(moduleId) {
+
+        if (moduleId.match(/^\.{1,2}\//)) {
+            moduleId = normalize(currentModule, moduleId)
+        }
+
+        if (hop(ModuleStore, moduleId)) {
+            var module = ModuleStore[moduleId]
+            if (module.__isLoading) {
+                if (WarnOnRecursiveRequire) {
+                    var fromModule = currentModule ? currentModule.id : "<root>"
+                    console.log("module '" + moduleId + "' recursively require()d from '" + fromModule + "', problem?")
+                }
+            }
+
+            currentModule.moduleIdsRequired.push(moduleId)
+
+            return module.exports
+        }
+
+        if (!hop(ModulePreloadStore, moduleId)) {
+            var fromModule = currentModule ? currentModule.id : "<root>"
+            error("module '" + moduleId + "' not found from '" + fromModule + "', must be define()'d first")
+        }
+
+        var factory = ModulePreloadStore[moduleId][0]
+        var prereqs = ModulePreloadStore[moduleId][1]
+
+        var module = create_module(moduleId)
+
+        var newRequire = get_require(module)
+
+        ModuleStore[moduleId] = module
+
+        module.__isLoading = true
+        try {
+            currentModule.moduleIdsRequired.push(moduleId)
+
+            var prereqModules = []
+            for (var i=0; i<prereqs.length; i++) {
+                var prereqId = prereqs[i]
+                var prereqModule
+
+                if      (prereqId == "require") prereqModule = newRequire
+                else if (prereqId == "exports") prereqModule = module.exports
+                else if (prereqId == "module")  prereqModule = module
+                else                            prereqModule = newRequire(prereqId)
+
+                prereqModules.push(prereqModule)
+            }
+
+            if (typeof factory == "function") {
+                var result = factory.apply(null, prereqModules)
+                if (result) {
+                    module.exports = result
+                }
+            }
+            else {
+                module.exports = factory
+            }
+        }
+        finally {
+            module.__isLoading = false
+        }
+
+        return module.exports
+    }
+
+    result.define         = require_define
+    result.implementation = PROGRAM
+    result.version        = VERSION
+
+    return result
+}
+
+//----------------------------------------------------------------------------
+// shorter version of hasOwnProperty
+//----------------------------------------------------------------------------
+function hop(object, name) {
+    return Object.prototype.hasOwnProperty.call(object, name)
+}
+
+//----------------------------------------------------------------------------
+// create a new module
+//----------------------------------------------------------------------------
+function create_module(id) {
+    return {
+        id:                id,
+        uri:               id,
+        exports:           {},
+        prereqIds:         [],
+        moduleIdsRequired: []
+    }
+}
+
+//----------------------------------------------------------------------------
+// reset the stores
+//----------------------------------------------------------------------------
+function require_reset() {
+    ModuleStore        = {}
+    ModulePreloadStore = {}
+    MainModule         = create_module(null)
+
+    require_define("modjewel", modjewel_module)
+
+    global.require    = get_require(MainModule)
+    global.define     = require_define
+    global.define.amd = true
+    global.modjewel   = require("modjewel")
+}
+
+//----------------------------------------------------------------------------
+// used by pre-built modules that can be included via <script src=>
+// a simplification of
+//    http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition
+// where id is required
+//----------------------------------------------------------------------------
+function require_define(moduleId, prereqs, factory) {
+    var rem = ["require", "exports", "module"]
+
+    if (typeof moduleId != "string") {
+        console.log("modjewel.define(): first parameter must be a string; was: " + moduleId)
+        return
+    }
+
+    if (arguments.length == 2) {
+        factory = prereqs
+        prereqs = null
+    }
+
+    if (!prereqs || prereqs.length == 0) {
+        prereqs = rem
+    }
+
+    if (typeof factory != "function") {
+        if (factory) {
+            ModulePreloadStore[moduleId] = [factory, prereqs]
+            return
+        }
+
+        console.log("modjewel.define(): factory was falsy: " + factory)
+        return
+    }
+
+    if (moduleId.match(/^\./)) {
+        console.log("modjewel.define(): moduleId must not start with '.': '" + moduleName + "'")
+        return
+    }
+
+    if (hop(ModulePreloadStore, moduleId)) {
+        console.log("modjewel.define(): module '" + moduleId + "' has already been defined")
+        return
+    }
+
+    ModulePreloadStore[moduleId] = [factory, prereqs]
+}
+
+//----------------------------------------------------------------------------
+// get the path of a module
+//----------------------------------------------------------------------------
+function getModulePath(module) {
+    if (!module || !module.id) return ""
+
+    var parts = module.id.split("/")
+
+    return parts.slice(0, parts.length-1).join("/")
+}
+
+//----------------------------------------------------------------------------
+// normalize a 'file name' with . and .. with a 'directory name'
+//----------------------------------------------------------------------------
+function normalize(module, file) {
+    var modulePath = getModulePath(module)
+    var dirParts   = ("" == modulePath) ? [] : modulePath.split("/")
+    var fileParts  = file.split("/")
+
+    for (var i=0; i<fileParts.length; i++) {
+        var filePart = fileParts[i]
+
+        if (filePart == ".") {
+        }
+
+        else if (filePart == "..") {
+            if (dirParts.length > 0) {
+                dirParts.pop()
+            }
+            else {
+                // error("error normalizing '" + module + "' and '" + file + "'")
+                // eat non-valid .. paths
+            }
+        }
+
+        else {
+            dirParts.push(filePart)
+        }
+    }
+
+    return dirParts.join("/")
+}
+
+//----------------------------------------------------------------------------
+// throw an error
+//----------------------------------------------------------------------------
+function error(message) {
+    throw new Error(PROGRAM + ": " + message)
+}
+
+//----------------------------------------------------------------------------
+// get a list of loaded modules
+//----------------------------------------------------------------------------
+function modjewel_getLoadedModuleIds() {
+    var result = []
+
+    for (moduleId in ModuleStore) {
+        result.push(moduleId)
+    }
+
+    return result
+}
+
+//----------------------------------------------------------------------------
+// get a list of the preloaded module ids
+//----------------------------------------------------------------------------
+function modjewel_getPreloadedModuleIds() {
+    var result = []
+
+    for (moduleId in ModulePreloadStore) {
+        result.push(moduleId)
+    }
+
+    return result
+}
+
+//----------------------------------------------------------------------------
+// get a module by module id
+//----------------------------------------------------------------------------
+function modjewel_getModule(moduleId) {
+    if (null == moduleId) return MainModule
+
+    return ModuleStore[moduleId]
+}
+
+//----------------------------------------------------------------------------
+// get a list of module ids which have been required by the specified module id
+//----------------------------------------------------------------------------
+function modjewel_getModuleIdsRequired(moduleId) {
+    var module = modjewel_getModule(moduleId)
+    if (null == module) return null
+
+    return module.moduleIdsRequired.slice()
+}
+
+//----------------------------------------------------------------------------
+// set the WarnOnRecursiveRequireFlag
+// - if you make use of "module.exports =" in your code, you will want this on
+//----------------------------------------------------------------------------
+function modjewel_warnOnRecursiveRequire(value) {
+    if (arguments.length == 0) return WarnOnRecursiveRequire
+    WarnOnRecursiveRequire = !!value
+}
+
+//----------------------------------------------------------------------------
+// relinquish modjewel's control of the require variable
+// - like jQuery's version'
+//----------------------------------------------------------------------------
+function modjewel_noConflict() {
+    NoConflict = true
+
+    global.require = OriginalRequire
+    global.define  = OriginalDefine
+}
+
+//----------------------------------------------------------------------------
+// the modjewel module
+//----------------------------------------------------------------------------
+function modjewel_module(require, exports, module) {
+    exports.VERSION                = VERSION
+    exports.require                = require
+    exports.define                 = require.define
+    exports.getLoadedModuleIds     = modjewel_getLoadedModuleIds
+    exports.getPreloadedModuleIds  = modjewel_getPreloadedModuleIds
+    exports.getModule              = modjewel_getModule
+    exports.getModuleIdsRequired   = modjewel_getModuleIdsRequired
+    exports.warnOnRecursiveRequire = modjewel_warnOnRecursiveRequire
+    exports.noConflict             = modjewel_noConflict
+}
+
+//----------------------------------------------------------------------------
+// log a message
+//----------------------------------------------------------------------------
+function log(message) {
+    console.log("modjewel: " + message)
+}
+
+//----------------------------------------------------------------------------
+// make the require function a global
+//----------------------------------------------------------------------------
+require_reset()
+
+//----------------------------------------------------------------------------
+})();
diff --git a/weinre.web/modules/weinre/client/Client.coffee b/weinre.web/modules/weinre/client/Client.coffee
index c85b126..41acfd9 100644
--- a/weinre.web/modules/weinre/client/Client.coffee
+++ b/weinre.web/modules/weinre/client/Client.coffee
@@ -52,13 +52,10 @@
         Weinre.WeinreClientCommands      = messageDispatcher.createProxy('WeinreClientCommands')
         Weinre.WeinreExtraClientCommands = messageDispatcher.createProxy('WeinreExtraClientCommands')
 
-        messageDispatcher.registerInterface(
-            'WeinreExtraTargetEvents', new WeinreExtraTargetEventsImpl(), false
-        )
-
-        messageDispatcher.registerInterface(
-            'WebInspector', WebInspector, false
-        )
+        messageDispatcher.registerInterface 'WeinreExtraTargetEvents', new WeinreExtraTargetEventsImpl(), false
+        messageDispatcher.registerInterface 'WebInspector',            WebInspector,                      false
+        messageDispatcher.registerInterface 'WeinreClientEvents',      new WeinreClientEventsImpl(this),  false
+        messageDispatcher.registerInterface 'InspectorFrontendHost',   InspectorFrontendHost,             false
 
         WebInspector.mainResource = {}
         WebInspector.mainResource.url = location.href
@@ -105,10 +102,6 @@
 
         @_installRemotePanel()
 
-        messageDispatcher = Weinre.messageDispatcher
-        messageDispatcher.registerInterface 'WeinreClientEvents', new WeinreClientEventsImpl(this), false
-        messageDispatcher.registerInterface 'InspectorFrontendHost', InspectorFrontendHost, false
-
     #---------------------------------------------------------------------------
     cb_registerClient: (clientDescription) ->
         Weinre.clientDescription = clientDescription
diff --git a/weinre.web/versions.js b/weinre.web/versions.js
index 0e4c545..65e516b 100644
--- a/weinre.web/versions.js
+++ b/weinre.web/versions.js
@@ -21,13 +21,5 @@
 
  Weinre.Versions = {
     weinre:   "@WEINRE_VERSION@",
-    build:    "@BUILD_NUMBER_DATE@",
-    jetty:    "@JETTY_VERSION@",
-    servlet:  "@JAVAX_SERVLET_VERSION@-@JAVAX_SERVLET_VERSION_IMPL@",
-    webkit:   "@WEBKIT_VERSION@",
-    cli:      "@CLI_VERSION@",
-    json4j:   "@JSON4J_VERSION@",
-    json2:    "@JSON2_VERSION@",
-    swt:      "@SWT_VERSION@",
-    modjewel: "@MODJEWEL_VERSION@"
+    build:    "@BUILD_DATE@",
  };